Windows Updateをコマンドから実行する方法

Windows Updateをコマンドから実行する方法。

企業などでは、Windowsマシンの更新を管理する場合、WSUS、Windows Intune、SCCMなどのMicrosoft製のツールを利用して集中管理するのが一般的ですが、ツールを利用するほど台数が多くない場合は、更新処理をスクリプト化してみてはいかがでしょうか。

更新処理をスクリプト化して、更新結果をテキストファイルでファイルサーバーなどに保存するようにしておけば、一台ずつ画面を開いて更新結果を確認する手間を削減できます。

そこでここでは、PowerShellコマンドレットやWindowsコマンドで更新プログラムのチェックやインストールを実行する方法を紹介します。

PowerShellの場合

Windows Update Agent APIを使った方法

Windows Update Agent API は、システム管理者やプログラマがWindows Updateにアクセスできるインターフェイスとして古くから利用されており、以下のようなPowerShellスクリプトを作成すれば、標準機能のみでWindows Updateを管理できます。

param(
[switch]$checkonly,
[switch]$downloadonly,
[switch]$importantonly,
[String]$kblistfile="1"
)

[Int]$ReturnCode=0

$date_msg = Get-date -Format "yyyy/MM/dd HH:mm:ss"
Write-Output ("Start : " + $date_msg)

[Array]$KBlist=@()
if (Test-Path $kblistfile){
    $KBlist= Get-Content $kblistfile
}

$UpdateCollection = New-Object -ComObject Microsoft.Update.UpdateColl
$Session = New-Object -ComObject Microsoft.Update.Session
$Searcher = New-Object -ComObject Microsoft.Update.Searcher
$Result = $Searcher.Search("IsInstalled=0 and Type='Software'")

Write-Output ""
Write-Output "■未適用更新プログラム一覧"
Write-Output "  * 重要な更新, o 推奨される更新"
Write-Output "  x オプションの更新でKBlistで指定されたもの, - 指定されていないオプションの更新"
Write-Output "  各行末尾のTrue/Falseはダウンロード済みかどうか"

[int]$countrequire=0
[int]$countrecommend=0
[int]$countoptionapply=0
[int]$countoption=0
foreach ($Updates in $Result.Updates){
    if($Updates.AutoSelectOnWebSites){
        if($Updates.EulaAccepted -eq 0){
            $Updates.AcceptEula()
        }
        $UpdateCollection.Add($Updates) | Out-Null
        Write-Output ("* "+$Updates.KBArticleIDs+" "+$Updates.Title+" "+$Updates.IsDownloaded)
        $countrequire++
    }elseif($Updates.BrowseOnly -eq $false){
        if($importantonly -eq $false){
            if($Updates.EulaAccepted -eq 0){
                $Updates.AcceptEula()
            }
            $UpdateCollection.Add($Updates) | Out-Null
        }
        Write-Output ("o "+$Updates.KBArticleIDs+" "+$Updates.Title+" "+$Updates.IsDownloaded)
        $countrecommend++
    }else{
        if($KBlist -contains $Updates.KBArticleIDs){
            if($Updates.EulaAccepted -eq 0){
                $Updates.AcceptEula()
            }
            $UpdateCollection.Add($Updates) | Out-Null
            Write-Output ("x "+$Updates.KBArticleIDs+" "+$Updates.Title+" "+$Updates.IsDownloaded)
            $countoptionapply++
        }else{
            Write-Output ("- "+$Updates.KBArticleIDs+" "+$Updates.Title+" "+$Updates.IsDownloaded)
            $countoption++
        }
    }
}

Write-Output ""
Write-Output ("  重要な更新: "+$countrequire+" 個")
Write-Output ("  推奨する更新: "+$countrecommend+" 個")
Write-Output ("  適用するオプション更新: "+$countoptionapply+" 個")
Write-Output ("  適用しないオプション更新: "+$countoption+" 個")
Write-Output ("  総数: "+$UpdateCollection.Count+" 個")
if($importantonly){
    Write-Output ("    → 推奨する更新は適用しません")
}

Write-Output ""

if($UpdateCollection.Count -eq 0){
    $date_msg = Get-date -Format "yyyy/MM/dd HH:mm:ss"
    Write-Output ("Normal End : " + $date_msg)
    exit 0
}

if($checkonly){
    $date_msg = Get-date -Format "yyyy/MM/dd HH:mm:ss"
    Write-Output ("Normal End : " + $date_msg)
    exit 0
}

$date_msg = Get-date -Format "yyyy/MM/dd HH:mm:ss"
Write-Output ""
Write-Output ("ダウンロード開始 "+$date_msg)
$Downloader = $Session.CreateUpdateDownloader()
$UpdateCollection | ForEach-Object {
    $Update=$_
    $date_msg = Get-date -Format "yyyy/MM/dd HH:mm:ss"
    Write-Output ("  "+$date_msg+" "+$Update.Title)
    $UpdateToDownload = New-object -com "Microsoft.Update.UpdateColl"
    $UpdateToDownload.Add($Update) | Out-Null
    $Downloader.Updates = $UpdateToDownload
    $DownloadResult = $Downloader.Download()
    Write-Output $("      ダウンロード終了コード" + $DownloadResult.ResultCode)
    if($DownloadResult.ResultCode -ne 2){
        Write-Output $Error[0]
    }
    [System.Runtime.Interopservices.Marshal]::ReleaseComObject($UpdateToDownload) | Out-Null
}

[Array]$FailedDownload=@()
foreach ($Updates in $UpdateCollection){
    if($Updates.IsDownloaded -eq $false){
        $FailedDownload+=$Updates.Title
    }
}
if($FailedDownload){
    Write-Output "ダウンロードが完了していない更新プログラム"
    $FailedDownload
    $date_msg = Get-date -Format "yyyy/MM/dd HH:mm:ss"
    Write-Output ("Abnormal End : " + $date_msg)
    exit 1
}

Write-Output "適用予定の更新プログラムのダウンロードが完了しました"

if($downloadonly){
    $date_msg = Get-date -Format "yyyy/MM/dd HH:mm:ss"
    Write-Output ("Normal End : " + $date_msg)
    exit 0
}

$date_msg = Get-date -Format "yyyy/MM/dd HH:mm:ss"
Write-Output ""
Write-Output ("更新プログラムの適用開始 "+$date_msg)
$Installer = New-Object -ComObject Microsoft.Update.Installer
$Installer.Updates = $UpdateCollection
$InstallResult = $Installer.Install()
Write-Output $("更新プログラムインストール終了コード" + $InstallResult.ResultCode)
if($InstallResult.RebootRequired){
    Write-Output "*** 再起動が必要です ***"
}

switch($InstallResult.ResultCode)
{
    2 {Write-Output "すべてのアップデートが適用されました"
    }

    3 {Write-Output "アップデート適用しましたがエラーも発生しました"
       Write-Output $Error[0]
       $ReturnCode=1
    }

    4 {    Write-Output "アップデート適用に失敗しました"
    Write-Output $Error[0]
    $ReturnCode=1
    }

    5 {    Write-Output "アップデート適用を中断しました"
    Write-Output $Error[0]
    $ReturnCode=1
    }

    default {Write-Output "アップデート適用がなんらかの理由で失敗しました"
    Write-Output $Error[0]
    $ReturnCode=1
    }
}


Write-Output ""
if($InstallResult.RebootRequired){
    Write-Output "*** 再起動が必要です ***"
}

if($ReturnCode -ne 0){
    New-Item $ErrorFile -ItemType file -Value "1" | Out-Null
    $date_msg = Get-date -Format "yyyy/MM/dd HH:mm:ss"
    Write-Output ("Abnormal End : " + $date_msg)
    exit 1
}

Write-Output ""
$date_msg = Get-date -Format "yyyy/MM/dd HH:mm:ss"
Write-Output ("Normal End : " + $date_msg)
exit 0

trap{
    Write-Output $error[0]
    $date_msg = Get-date -Format "yyyy/MM/dd HH:mm:ss"
    Write-Output ("Abnormal End : " + $date_msg)
    exit 1
    break
}

上のスクリプトでは、たとえばオプションとして「-scanonly」を付加すれば更新のチェックのみを実行でき「-importantonly」を付加して実行すれば重要な更新プログラムをインストールできます。

WindowsUpdateモジュールを使った方法

PowerShellで、より簡単にWindows Updateの更新プログラムのチェックやインストールを行いたい場合は、WindowsUpdateモジュールを使った方法がおすすめです。

WindowsUpdateモジュールを使って更新プログラムのチェックやインストールを実行する方法は、まず、以下のコマンドでWindowsUpdateモジュールを使用できるようにします。

if (-not(Test-Path ".\Modules")){New-Item -Path ".\Modules" -ItemType Directory}
Save-Module -Name PSWindowsUpdate -Path ".\Modules"
Import-Module ".\Modules\PSWindowsUpdate"

モジュールを使えるようにした後は、更新プログラムの有無をチェックするときは、以下のコマンドを実行します。

PS> Get-WindowsUpdate

更新プログラムをダウンロードまで行いたいときは、以下のコマンドを実行します。

PS> Get-WindowsUpdate -Download

必要な更新プログラムのインストールまで行いたいときは、以下のコマンドを実行します。更新プログラムのインストール後に再起動が必要な場合は、再起動するかの質問が表示されます。

PS> Get-WindowsUpdate -Install -AcceptAll

更新プログラムのインストール後に自動的に再起動させたいときは、以下のようにコマンドを実行します。

PS> Get-WindowsUpdate -Install -AcceptAll -AutoReboot

更新プログラムの適用履歴を確認したいときは、以下のコマンドを実行します。

PS> Get-WUHistory

Windows Updateをコマンドから実行する方法。

なお、ここでは基本的なコマンドの紹介のみでしたが、WindowsUpdateモジュールには、重要な更新のみを適用するなどのオプションも用意されているので、より詳しい使い方を知りたい方は、以下のコマンドでヘルプを確認してみるとよいでしょう。

PS> Get-Help Get-WindowsUpdate -detailed

Windowsコマンドの場合

Windowsコマンドで、Windows Updateの更新プログラムのチェックやインストールを行う方法としては「UsoClient.exe」を使った方法がありますが、UsoClientでは、画面上に実行状況などがほとんど表示されないため、個人的には上に紹介したPowerShellコマンドレットを使った方法をおすすめします。

参考までに、UsoClientを使った方法を紹介しておきます。

以降で紹介しているコマンドは、すべて管理者としてコマンドプロンプトを起動して実行します。

必要な更新プログラムの有無のチェックだけを行いたいときは、以下のコマンドを実行します。

C:¥> UsoClient StartScan

必要な更新プログラムのダウンロードまでを行いたいときは、以下のコマンドを実行します。

C:¥> UsoClient ScanInstallWait

更新プログラムをインストールするときは、以下のコマンドを実行します。

C:¥> UsoClient StartInstall