WUA API で WSUS から取得した更新プログラムを任意のタイミングで適用する

Last Update: feedback 共有

こんにちは、Japan Developer Support Core チームの近澤です。

WSUS から Windows Update を配信する構成は、Windows Update Agent (WUA) API を使用してスクリプトから実行することが可能です。
これにより、配信する更新プログラムの検索、選定、ダウンロード、インストールを自動化することができます。

Windows Update エージェント API - Win32 apps | Microsoft Learn

さて、組織で更新プログラムを管理する際、検証環境と本番環境を分け、十分に検証を実施した後に、本番環境に同じ更新プログラムを当てたい、という要望がよくあります。
WUA API の使用例は、下記ドキュメントなどにありますが、この例では、スクリプトの中で検索、ダウンロード、インストールをひとまとめにして実施しています。
そのため、例えば、検証環境にインストールした更新プログラムと全く同じものを、その1か月後に本番環境にインストールしたい場合、このスクリプトでは1か月後に新しくリリースされた更新プログラムも含まれてしまい、検証環境と同じ更新プログラムを当てることができません。

更新の検索、ダウンロード、インストール - Win32 apps | Microsoft Learn

そのような状況に対処するための方法をご紹介します。

UpdateID をファイルに保持する対処方法について

更新プログラムには UpdateID という一意の識別子が用意されています。
検証環境に更新プログラムをインストールする際に、あらかじめ Update ID を保持しておき、本番環境への適用時にその ID の更新プログラムのみを検索し、ダウンロード・インストールするという方法があります。
下記のサンプルのスクリプトをご参考ください。
なお、下記では、C:\WU\PATCH_LIST.txt というテキストファイルに書き出しています。

<更新を検索し、テキストファイルへ書き出すスクリプト>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
###################################
# Check Updates and Write to file
###################################
# Load the Windows Update Agent (WUA) COM object
$updateSession = New-Object -COM "Microsoft.Update.Session"
# Create an update searcher
$updateSearcher = $updateSession.CreateUpdateSearcher()
# Search for available updates
$searchResult = $updateSearcher.Search("IsInstalled=0")
# Check updates
$updatesExcludingFU = New-Object -COM "Microsoft.Update.UpdateColl"
foreach ($update in $searchResult.Updates) {
$updatesExcludingFU.Add($update) | Out-Null
}
# Write to file
$updatesExcludingFU | ForEach-Object {$_.Identity.UpdateID} >> C:\WU\PATCH_LIST.txt

<テキストファイルを読み込み、ダウンロード・インストールするスクリプト>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
########################################
# Download & Install Update from file
########################################
# Read file
$updateIds = Get-Content -Path C:\WU\PATCH_LIST.txt
# Load the Windows Update Agent (WUA) COM object
$updateSession = New-Object -COM "Microsoft.Update.Session"
# Create an update searcher
$updateSearcher = $updateSession.CreateUpdateSearcher()
# Search for available updates
$searchResult = $updateSearcher.Search("IsInstalled=0")
# Get target updates
$updatesToDownload = New-Object -COM "Microsoft.Update.UpdateColl"
$updatesToInstall = New-Object -COM "Microsoft.Update.UpdateColl"
foreach ($update in $searchResult.Updates) {
if ($update.Identity.UpdateID -in $updateIds) {
# for download
if ($update.IsDownloaded -eq $false) {
$updatesToDownload.Add($update) | Out-Null
}
# for install
$updatesToInstall.Add($update) | Out-Null
}
}
Echo "Updates to download"
$updatesToDownload | Sort-Object -Property title | Format-Table Title
Echo "Updates to install"
$updatesToInstall | Sort-Object -Property title | Format-Table Title
# Download
if ($updatesToDownload.Count -gt 0) {
$downloader = $updateSession.CreateUpdateDownloader()
$downloader.Updates = $updatesToDownload
$downloadResult = $downloader.Download()
$downloadResult
}
# Install the loaded updates
if ($updatesToInstall.Count -gt 0) {
$installer = $updateSession.CreateUpdateInstaller()
$installer.Updates = $updatesToInstall
$installationResult = $installer.Install()
$installationResult
}


本ブログの内容は弊社の公式見解として保証されるものではなく、開発・運用時の参考情報としてご活用いただくことを目的としています。もし公式な見解が必要な場合は、弊社ドキュメント (https://docs.microsoft.comhttps://support.microsoft.com) をご参照いただくか、もしくは私共サポートまでお問い合わせください。