2010/07/05

Windows Scripting: Windows Update をスクリプトから ( WindowsUpdate.ps1 )

今回は、前回の Windows Update 用 WSH スクリプト WindowsUpdate.vbs の、PowerShell スクリプト版 Windows Update.ps1 です。


WUA API の PowerShell スクリプトのサンプルは少ないようです。私の場合、Scripting Guy 大先生の以下のサイトを参考にしました。

更新プログラムを検索、ダウンロード、およびインストールする方法はありますか
http://www.microsoft.com/japan/technet/scriptcenter/resources/qanda/mar09/hey0311.mspx

WSH の VBScript を PowerShell スクリプトに直訳すれば大丈夫なようです。それでもよかったのですが、ダウンロード済みの場合はダウンロードしない処理や、準備ができていない場合 (ダウンロード失敗した場合?) にインストールしない処理を追加したりと、ちょっとだけ工夫しています。メッセージを英語にしたのには、それほど意味はありません。

このスクリプトを実行するには、PowerShell の ExecutionPolicy を RemoteSigned に変更する必要があります (あるいはスクリプトに署名します)。また、PowerShell のシェルを管理者として実行で開かないと、Download() や Install () がエラーになりますのでご注意を (1 日ほどこれで悩みました)。

前回と同様に、このスクリプトは COM インターフェイスである WUA (Windows Update Agent) API を使用して、ローカル PC に必要な更新プログラムがないかどうか検索し、ダウンロードして、インストールします。再起動が必要な場合は、即座に再起動(またはシャットダウン)します。

[windowsupdate.ps1]
Write-Host "--- Running Windows Update ---"
Write-Host "Searching for updates..."
$updateSession = new-object -com "Microsoft.Update.Session"
$updateSearcher = $updateSession.CreateupdateSearcher()
$searchResult = $updateSearcher.Search("IsInstalled=0 and Type='Software' and AutoSelectOnWebSites=1")
Write-Host "List of applicable items on the machine:"
if ($searchResult.Updates.Count -eq 0) {
 Write-Host "There are no applicable updates."
}
else
{
 $downloadReq = $False
 $i = 0
 foreach ($update in $searchResult.Updates){
  $i++
  if ( $update.IsDownloaded ) {
   Write-Host $i">" $update.Title "(downloaded)"
  }
  else
  {
   $downloadReq = $true
   Write-Host $i">" $update.Title "(not downloaded)"
  }
 }
 if ( $downloadReq ) {
  Write-Host "Creating collection of updates to download..."
  $updatesToDownload = new-object -com "Microsoft.Update.UpdateColl"
  foreach ($update in $searchResult.Updates){
   $updatesToDownload.Add($update) | out-null
  }
  Write-Host "Downloading updates..."
  $downloader = $updateSession.CreateUpdateDownloader()
  $downloader.Updates = $updatesToDownload
  $downloader.Download()
  Write-Host "List of downloaded updates:"
  $i = 0
  foreach ($update in $searchResult.Updates){
   $i++
   if ( $update.IsDownloaded ) {
    Write-Host $i">" $update.Title "(downloaded)"
   }
   else
   {
    Write-Host $i">" $update.Title "(not downloaded)"
   }
  }
 }
 else
 {
  Write-Host "All updates are already downloaded."
 }
 $updatesToInstall = new-object -com "Microsoft.Update.UpdateColl"
 Write-Host "Creating collection of downloaded updates to install..."
 foreach ($update in $searchResult.Updates){
  if ( $update.IsDownloaded ) {
   $updatesToInstall.Add($update) | out-null
  }
 }
 if ( $updatesToInstall.Count -eq 0 ) {
  Write-Host "Not ready for installation."
 }
 else
 {
  Write-Host "Installing" $updatesToInstall.Count "updates..."
  $installer = $updateSession.CreateUpdateInstaller()
  $installer.Updates = $updatesToInstall
  $installationResult = $installer.Install()
  if ( $installationResult.ResultCode -eq 2 ) {
   Write-Host "All updates installed successfully."
  }
  else
  {
   Write-Host "Some updates could not installed."
  }
  if ( $installationResult.RebootRequired ) {
   Write-Host "One or more updates are requiring reboot."
   Write-Host "Reboot system now !!"
   shutdown.exe /r /t 0
   # Write-Host "Shutdown system now !!"

   # shutdown.exe /s /t 0
  }
  else
  {
   Write-Host "Finished. Reboot are not required."
  }
 }
}

Windows 7 および Windows Server 2008 R2 の PowerShell 2.0 から、PowerShell Remoting がサポートされました。これをうまくからめることで、リモートから Windows Update を実行できそうです。
↑ダメでした。
Windows Scripting: Windows Update をリモートから ( PowerShell Remoting は NG )
Windows Scripting: Windows Update をリモートから ( WinRM/WinRS も NG )

0 件のコメント: