連載
» 2019年01月22日 05時00分 公開

山市良のうぃんどうず日記(145):更新プログラムのダウンロード/インストール進捗状況が知りたい――Windows 10(バージョン1709以降)の更新用スクリプト解説

Windows 10 バージョン1709以降では、「WindowsUpdateProvider」モジュールが利用可能になりました。今回は、このモジュールのWindows Update用コマンドレットを利用した、汎用的に使える筆者自作のPowerShellスクリプト「SearchAndInstallUpdates.ps1」を紹介します。

[山市良,テクニカルライター]
「山市良のうぃんどうず日記」のインデックス

山市良のうぃんどうず日記

きっかけは、Server Coreで更新のダウンロード/インストール進捗状況が見たい

 2018年12月の定例更新(第二火曜日の翌日)リリース時期に、主にWindows ServerのServer Coreインストール環境での利用を想定した、更新プログラムのダウンロードとインストール用PowerShellスクリプト「SearchAndInstallUpdates.ps1」を作成しました。

 その後、品質更新プログラムのリリースに合わせて、複数回、動作確認テストができたので紹介します。このスクリプトは「TechNetスクリプトセンター」で公開していますので、興味のある方はこちらから入手してください。

 Server Coreインストール環境は、GUIのデスクトップ環境やツールが削除されています。Windows Updateによる更新プログラムのダウンロートとインストールは、Server Core用の「Sconfig」(サーバ構成)ユーティリティーのメニューから実行できます。

 しかし、「更新プログラムをダウンロードしています」「更新プログラムをインストールしています」と表示されるだけで、その間の進捗(しんちょく)状況、つまりどれくらいダウンロードが進んでいるのか、どれくらいインストールが進んでいるのか全く分かりません(画面1)。

画面1 画面1 Server Coreでは「Sconfig」ユーティリティーの「6)更新プログラムのダウンロードとインストール」を選択することで、更新プログラムの確認、ダウンロード、インストールを実行できるが、進捗状況が分からない

 これが、PowerShellスクリプト「SearchAndInstallUpdates.ps1」を作成したきっかけです(画面2)。

画面2 画面2 筆者自作のPowerShellスクリプト「SearchAndInstallUpdates.ps1」は、更新プログラムごとにダウンロードとインストールの進捗状況、インストールの成功/失敗を確認できる

 PowerShellスクリプト「SearchAndInstallUpdates.ps1」は、下記の連載記事で紹介した「WindowsUpdateProvider」モジュールのコマンドレットを利用しています。

 WindowsUpdateProviderモジュールは、Windows 10 バージョン1709/Windows Server,version 1709から利用可能になった、Windowsに標準搭載されているPowerShellモジュールです。前記の連載記事では、PowerShellウィンドウから更新プログラムの確認、ダウンロード、インストールを行うための、数行の簡単なコマンドラインを紹介しました。

PowerShellスクリプトコードの解説

 PowerShellスクリプト「SearchAndInstallUpdates.ps1」の完全な内容は、TechNetスクリプトセンターの説明やダウンロードファイルで確認できます。本稿では、ポイントを絞って解説します(説明を簡単にするため、一部コードを変更しています)。このスクリプトを必要としない場合でも、使っているテクニックは別のスクリプト作成で役に立つかもしれません。

 スクリプトの先頭にある以下のコードでは、WindowsUpdateProviderモジュールが存在するかどうかを確認し、利用できない場合は、システム要件を示すメッセージを表示します。エラーを無視してモジュールをインポートさせて、モジュールの情報を取得できるかどうかで利用可能であるかどうかを判断しています。

Import-Module WindowsUpdateProvider -ErrorAction SilentlyContinue 
$checkmodule = (Get-Module WindowsUpdateProvider) 
if ($checkmodule -eq $null) { 
  Write-Host "This script can be run on Windows 10/Server ver 1709(RS3) or later." 
  exit 
} 

 以下のコードは、レジストリの「HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion」キーにある「ProductName」「ReleaseId」「CurrentBuild」「UBR」の値を取得して、「Product Name(製品名)」「OS Version(YYMM形式のバージョン)」「Current OS Build(現在の詳細なOSビルド番号)」を出力しています。更新プログラムのダウンロードとインストールには直接関係のない、おまけの機能です。

(Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").ProductName 
(Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").ReleaseId 
(Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").CurrentBuild + "." + (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").UBR

 以下のコードは、WindowsUpdateProviderモジュールの「Get-WULastScanSuccessDate」と「Get-WULastInstallationDate」コマンドレットを使用し、「Last Check date(更新プログラムの最終チェック日時)」「Last Installation date(更新プログラムの最終インストール日時)」を出力します。なお、Server Coreインストール環境ではこれらのコマンドレットは正しい値を返さない場合があるようです(画面3)。

(Get-WULastScanSuccessDate).DateTime
(Get-WULastInstallationDate).DateTime
画面3 画面3 システム情報と更新日時の情報の表示

 更新プログラムの確認とダウンロード、インストールの部分は、以下のようなコードになっています。更新プログラムを確認し、ダウンロード、インストールするかどうかを問い合わせて「A(またはa)」と入力された場合は、全ての更新プログラムを対象に、更新プログラムごとにダウンロードとインストールを行い、更新プログラムごとにインストール結果を示します。また、必要があれば再起動を開始するという処理を、WindowsUpdateProviderモジュールの「Start-WUScan」「Install-WUUpdates」「Get-WUIsPendingReboot」コマンドレットで実現しています。

$updates = Start-WUScan
if ($updates .Count -gt 0) {
    $i = 1 
    foreach ($update in $updates) { 
        Write-Host $i")" $update.Title 
        $i = $i + 1 
    } 
    $res = Read-Host "(A)ll updates, (N)o update ? (a/n) "
    if (($res -eq "a") -or ($res -eq "A")) {
        foreach ($update in $updates) { 
            Write-Host "Update:" $update.Title 
            $result = (Install-WUUpdates -Updates $update -ErrorAction SilentlyContinue) 
            if ($result) { 
                Write-Host "Installation Result: Succeeded" 
            } else { 
                Write-Host "Installation Result: Failed with errors." 
            } 
        }
    } else {
        exit
    }
    if (Get-WUIsPendingReboot) {
        $res = Read-Host "A restart is required to complete Windows Updates. Restart now? (y/n) " 
        if (($res -eq "y") -or ($res -eq "Y")) {
             Write-Host "Start rebooting..."
             Restart-Computer -Force
        } else {
            Write-Host "You need to restart later." 
        }
    }
} else { 
    Write-Host "There are no applicable updates." 
}

 Start-WUScanコマンドレットは、利用可能な更新プログラムが1つ以上ある場合、その情報を返します。Install-WUUpdatesコマンドレットは、インストールが成功すると「True」を、失敗すると「False」を返します。Get-WUIsPendingRebootコマンドレットは、更新プログラムのインストールのために再起動が保留されているものがある場合、「True」を返します。

 なお、上記コードは全ての更新プログラムを検出された順番にインストールするため、インストール順が重要な場合は一部のインストールに失敗することがあります。その場合は、コンピュータを再起動せずに、もう一度、スクリプトを実行することで成功すると思います。

想定はServer Coreだが、デスクトップエクスペリエンス環境やWindows 10でも動作

 PowerShellスクリプト「SearchAndInstallUpdates.ps1」は、「設定」アプリを利用できないServer Coreインストール環境での利用を想定して作成しました。ですが、Windows 10 バージョン1709およびWindows Server,version 1709以降の標準機能を利用したものであり、Windows 10やWindows Server 2019のデスクトップエクスペリエンス環境でも利用できるはずです(画面4)。

画面4 画面4 Windows 10 バージョン1803を「SearchAndInstallUpdates.ps1」で更新しているところ。スクリプトの実行時に管理者権限は不要だが、PowerShellスクリプトの実行ポリシーの変更が必要な場合がある(Set-ExecutionPolicy RemoteSignedなど)

 ただし、Windows 10ではStart-WUScanコマンドレットが、以下のようなエラーで終了する場合があることを確認しています。このエラーの原因や回避方法を筆者は見つけることができていません。

Start-WUScan : Scan hit error: @{PSComputerName=}.ReturnValue

 なお、このスクリプトはSconfigユーティリティーの場合と同様、CリリースやDリリースの累積更新プログラム(新たなセキュリティ修正を含まない更新プログラムのプレビュー)を検出しないはずです。

 CリリースやDリリースについては、以下の記事を参照してください。Windows 10の機能更新プログラムの自動配布が開始された場合、このスクリプトのインストール対象として検出されるかどうかは確認していません。

 また、Windows Updateの自動更新が有効になっている環境では、バックグラウンドでダウンロードとインストールが進んでいる場合があるため、正常に機能しない可能性があります。スクリプトを利用する場合は、Sconfigユーティリティー(デスクトップエクスペリエンス環境でも利用できます)やグループポリシーを使用して、「手動更新」(ダウンロードと自動インストールを通知)に切り替えてから実行してください。自動更新を無効にできないWindows 10 Homeエディションでは使用しないことをお勧めします。

補足情報(2019年1月25日追記)

 このスクリプトがWindows 10 バージョン1709以降およびWindows Server,version1709以降のCリリースやDリリースの累積更新プログラムを検出しないことを確認しました。

 しかし、Windows 10 バージョン1809、Windows Server 2019、Windows Server,version 1809向けの.NET Framework更新プログラム「KB4481031」(Dリリースに相当するプレビュー累積更新)を検出することが分かりました。

 「KB4481031」はリリース当初、Microsoft側のミスで自動配布対象となっていましたが、現在は「更新プログラムのチェック」のクリックでインストールされるオプションになりました。

 しかし、このスクリプトおよびWindows ServerのSconfigユーティリティーの「すべての更新プログラム(A)」は、依然として「KB4481031」を検出します。以下のように、スクリプトの2行をコメントアウトして、新たに2行を追加することで「KB4481031」は検出されなくなります。この変更は、Sconfigユーティリティーの「推奨される更新プログラムのみ(R)」と同じ結果になります。

# Write-Host "`r`nSearching for all applicable updates..."
# $updates = Start-WUScan
Write-Host "`r`nSearching for recommended updates..."
$updates = Start-WUScan -SearchCriteria "IsInstalled=0 and Type='Software' and AutoSelectOnWebsites=1"

筆者紹介

山市 良(やまいち りょう)

岩手県花巻市在住。Microsoft MVP:Cloud and Datacenter Management(2018/7/1)。SIer、IT出版社、中堅企業のシステム管理者を経て、フリーのテクニカルライターに。Microsoft製品、テクノロジーを中心に、IT雑誌、Webサイトへの記事の寄稿、ドキュメント作成、事例取材などを手掛ける。個人ブログは『山市良のえぬなんとかわーるど』。近著は『ITプロフェッショナル向けWindowsトラブル解決 コマンド&テクニック集』(日経BP社)。


Copyright © ITmedia, Inc. All Rights Reserved.

「Windows 7」サポート終了 対策ナビ

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。