この記事はcorp-engr 情シスSlack(コーポレートエンジニア x 情シス)#1 Advent Calendar 2023の12/2分の記事です。ずいぶん遅れてやってきてしまいました。

Microsoft Intuneでエンロールされているデバイスは、デフォルトで8時間ごとにサーバーと同期を行います。 この同期時間をワークロードによっては変更したい場合があります。

今回は、Microsoft Intune管理下のWindowsデバイスの同期サイクルを変更する方法を紹介します。

Windowsデバイスのサーバーとの定期的な同期の仕様

Microsoft Intuneのポリシーとプロファイルに関する質問 | Microsoft Learnによると、Windowsデバイスのサーバーとの定期的な同期は約8時間ごとに実行されます。

プラットフォーム 更新サイクル
Android 約8時間ごと
iOS/iPadOS 約8時間ごと
macOS 約8時間ごと
Windows 10/11のPCをデバイスとして登録 約8時間ごと
Windows 8.1 約8時間ごと

実際にデバイス上の設定を確認してみると、タスクスケジューラの \Microsoft\Windows\EnterpriseMgmt\エンロールID のタスクパスに登録されている Schedule #3 created by enrollment client タスクに、該当のトリガーが設定されていることが分かります。

タスクスケジューラにおける、8時間ごとにMicrosoft Intuneと同期するタスク

また、ドキュメントには以下のように、条件によっては同期時間が変わることが記載されています。

デバイスを最近登録した場合は、コンプライアンス、コンプライアンス違反、構成のチェックインの実行頻度が高くなります。 チェックインは、次のように推定されます。

プラットフォーム 頻度
Android 15分まで3分ごと、その後の2時間は1分ごと、その後は約8時間ごと
iOS/iPadOS 1時間まで15分ごと、その後は約8時間ごと
macOS 1時間まで15分ごと、その後は約8時間ごと
Windows 10/11のPCをデバイスとして登録 15分まで3分ごと、その後の2時間は15分ごと、その後は約8時間ごと
Windows 8.1 15分まで5分ごと、その後の2時間は15分ごと、その後は約8時間ごと

こちらも、タスクスケジューラの \Microsoft\Windows\EnterpriseMgmt\エンロールID のタスクパスに登録されている、

  • Schedule #1 created by enrollment client
  • Schedule #2 created by enrollment client

のタスクに、該当のトリガーが設定されていることが分かります。

タスクスケジューラにおける、いつくかの条件においてMicrosoft Intuneと同期するタスク

同期サイクルを変更する

前述の通り、8時間ごとにMicrosoft Intuneと同期するタスクは Schedule #3 created by enrollment client でした。 このサイクルを変更したい場合は、トリガーの「繰り返し間隔」を変更することで実現できます。

このタスクは管理者権限で作成されているため、以下の操作も管理者権限で行う必要があります。

  1. Schedule #3 created by enrollment client > [プロパティ] > [トリガー] を選択
  2. [編集] > [繰り返し間隔] から時間を変更

エンロールされた際のこのタスクが作成されるため、以降タスクの設定が上書きされることは基本的にはありません。 ただ、今後Microsoft Intuneの仕様が変わって、Windows Updateなどの後にタスクが作り直される可能性はあります。

同期サイクルの変更を自動化する

上記の手順を行えば同期サイクルを変更できますが、キッティング時に1台1台手動で設定するのはたいへんです。 そこで、1台1台手動で設定するのではなく、手順をスクリプト化したものMicrosoft Intuneで配布することで、この作業を自動化できます。

同期サイクルを変更するスクリプト

以下は、例として同期サイクルを1時間に変更するスクリプトです。 $repetitionIntervalに変更したい同期サイクルを設定しています。必要に応じて変更してください。

# 同期サイクルとして設定したい時間を指定
# ISO 8601で定義されている、継続時間が指定可能
$repetitionInterval = "PT1H"

# オブジェクトをDeep Cloneするための関数
function Copy-Object {
  Param (
    [Parameter(Mandatory = $false)]
    $Original,

    [Parameter(Mandatory = $true)]
    [ref] $DeepClone
  )

  if ($null -eq $Original) {
    $DeepClone.Value = $null
  }
  else {
    $memStream = new-object IO.MemoryStream
    $formatter = new-object Runtime.Serialization.Formatters.Binary.BinaryFormatter
    $formatter.Serialize($memStream, $Original)
    $memStream.Position = 0
    $DeepClone.Value = $formatter.Deserialize($memStream)
    $memStream.Close()
  }
}

try {
  # Intuneに関係するスケジュールタスクを取得
  $scheduledTasks = Get-ScheduledTask | Where-Object { ($_.TaskPath) -Match "\\Microsoft\\Windows\\EnterpriseMgmt\\[0-9A-Z]" }
  if (!$scheduledTasks) {
    Write-Host "This device is not enrolled"
    exit 0
  }

  # 「Schedule #3 created by enrollment client」のタスクを取得
  $intuneSyncTaskCandidate = $scheduledTasks | Where-Object { ($_.TaskName) -Match "^Schedule #3 created by enrollment client$" }
  if (!$intuneSyncTaskCandidate) {
    Write-Host "Not found intune sync tasks, please check task name on device"
    exit 1
  }

  $intuneSyncTask = $intuneSyncTaskCandidate[0]
  if (!$intuneSyncTask.Triggers) {
    Write-Host "Not found triggers at '$($intuneSyncTask.TaskName)' task"
    exit 1
  }

  # すでに同期サイクルが設定されている場合は処理を止める
  if ($intuneSyncTask.Triggers[0].Repetition.Interval -eq $repetitionInterval) {
    Write-Host "Repetition interval of task is already set as $repetitionInterval"
    exit 0
  }

  # 同期サイクルを設定するために、すでに設定されいてる'MSFT_TaskTimeTrigger'インスタンスを複製して、Intervalを上書きしている
  # Deep Cloneまでする必要はないかもしれないが、ミュータブルは副作用があるかもしれないため、イミュータブルなインスタンスを作成している
  $trigger = $null
  Copy-Object -Original $intuneSyncTask.Triggers[0] -DeepClone ([ref]$trigger)
  if (!$trigger) {
    throw "The instance could not be copied and became null by Copy-Object function"
  }
  $trigger.Repetition.Interval = $repetitionInterval

  # 編集したトリガーを該当タスクに設定
  Set-ScheduledTask -TaskPath $intuneSyncTask.TaskPath -TaskName $intuneSyncTask.TaskName -Trigger $trigger
}
catch {
  Write-Host "An unexpected error has occurred"
  throw $_
}

exit 0

スクリプトの配布

Microsoft IntuneでPowerShellを配布する場合、選択肢としては大きく以下の3通りがあります。

  • スクリプト機能で配布
  • Win32アプリ(.intunewin)として配布
  • プロアクティブな修復のスクリプトパッケージとして配布

今回は「プロアクティブな修復のスクリプトパッケージとして配布」を使用して、上記のスクリプトを配布してみます。 これにより、もしWindows Updateなどで設定値がデフォルトに戻る場合でも、自動的に設定値を期待通りに設定し直せます。

  1. Microsoft Intune管理センター > [デバイス] > [修復] から、スクリプトパッケージの作成を選択

    プロアクティブな修復

  2. 任意の名前を入力

    カスタムスクリプトの作成 - 基本

  3. 作成したスクリプトを「検出スクリプト」としてアップロード、「64 ビットの PowerShell でスクリプトを実行する」をはいに設定

    カスタムスクリプトの作成 - 設定

  4. 任意でスコープタグを設定

    カスタムスクリプトの作成 - スコープタグ

  5. 割り当て先を設定
    • 割り当てのポリシーは自由に選択できるが、ここでは、すべてのデバイスに対して、毎日実行するように設定

    カスタムスクリプトの作成 - 割り当て

  6. 内容を確認して作成

    カスタムスクリプトの作成 - 確認および作成

終わりに

Microsoft Intune管理下のWindowsデバイスの同期サイクルを変更する方法を紹介しました。

Microsoft Intuneの場合、ポリシーを適用してもすぐには反映されず、該当デバイスの設定画面から同期を行ったり、インベントリの「同期」コマンドを実行したりするような運用となることが多いと思います。

今回の方法を使用することで、たとえば、組織のデバイスに対して一律で同期サイクルを短くすることで、よりすばやくポリシーが適用でき、迅速なデバイスの保護や情報の収集ができ、運用の効率化ができるかもしれません。