$cred = Import-Clixml $HOME\vm01-cred.xml $vmName = "vm01" # https://www.say-tech.co.jp/contents/blog/yamanxworld/2025vol124 $updateScriptPath = "E:\Tools\WUA_SearchDownloadInstall.ps1" $guestTargetPath = "C:\" $vm = Get-VM -Name $vmName -ErrorAction Stop # チェックポイントの作成 $vm | CheckPoint-VM -SnapshotName "Pre Update" # ゲスト サービスの現在の設定の退避と有効化 # Enable VMGuestSvc #$vmGuestSvcDefault = (Get-VMIntegrationService -VMName $vm.Name "ゲスト サービス インターフェイス").Enabled #if (!$vmGuestSvcDefault) { # Enable-VMIntegrationService -VMName $vm.Name "ゲスト サービス インターフェイス" #} $vmGuestSvc = $vm | Get-VMIntegrationService | Where{ $_.id -eq "Microsoft:$($vm.id)\6C09BB55-D683-4DA0-8931-C9BF705F6480"} $vmGuestSvcDefault = $vmGuestSvc.Enabled if (!$vmGuestSvcDefault) { Enable-VMIntegrationService -VMName $vm.Name $vmGuestSvc.Name } # VMの開始(ゲスト起動まで待機) $vm | Start-VM -ErrorAction Stop Write-Host "`r$($vm.Name) is Starting... " -NoNewLine While ($vm.Heartbeat -notlike "Ok*") { Start-Sleep 1 } Write-Host "`r$($vm.Name) is Online " -NoNewLine # Windows Update Scriptをゲストにコピー Write-Host "`rStart Windows Update... " -NoNewLine Copy-VMFile -Name $vm.Name -SourcePath $updateScriptPath -DestinationPath $guestTargetPath -FileSource Host -Force # ゲスト サービスを以前の設定に戻す if (!$vmGuestSvcDefault) { # Disable-VMIntegrationService -VMName $vm.Name "ゲスト サービス インターフェイス" Disable-VMIntegrationService -VMName $vm.Name $vmGuestSvc.Name } # Windows Update スクリプトの実行 $updateScript = Join-Path "C:\" (Split-Path $updateScriptPath -Leaf) Invoke-Command -VMName $vm.Name -Credential $cred -ScriptBlock { & $using:updateScript -Automate } # 再起動待ち? $rebootReq = Invoke-Command -VMName $vm.Name -Credential $cred -ScriptBlock {if ((Test-Path "HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired") -or (Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending")) { return $true } else { return $false} } # 再起動待ちなら再起動 if ($rebootReq) { Write-Host "`rReboot required to complete update." -NoNewLine Invoke-Command -VMName $vm.Name -Credential $cred -ScriptBlock {Restart-Computer -Force} # Wait until "NoConnect" while ($vm.HeartBeat -like "Ok*") { Write-Host "`rConfiguring Windows Update... " -NoNewLine start-sleep 1 } Write-Host "`r$($vm.Name) is Restarting... " -NoNewLine # Wait "Ok*" 900 seconds in a row $countdown = 900 while ($countdown -gt 0) { if ($vm.HeartBeat -like "Ok*") { Write-Host "`rPlease wait $($countdown) sec... " -NoNewLine $countdown-- } else { Write-Host "`r$($vm.Name) is Restarting... " -NoNewLine if ($countdown -ne 900) { $countdown = 900 } } start-sleep 1 } } # シャットダウン前に現在のOSビルドを取得(メモ用) $osbuild = Invoke-Command -VMName $vm.Name -Credential $cred -ScriptBlock {$cv = Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion';"$($cv.CurrentBuild).$($cv.UBR)"} # VMのシャットダウン Write-Host "`r$($vm.Name) is Stopping... " -NoNewLine $vm | Stop-VM -Force -ErrorAction Stop While ($vm.State -ne "Off") { Start-Sleep 1 } Write-Host "`r$($vm.Name) is Off " -NoNewLine # VM メモ更新 $addnote = "$(Get-Date -Format 'yyyy/MM/dd HH:mm:ss') Windows Update 完了(OSビルド: $($osbuild))" $notes = if ($vm.Notes) { $addnote + "`r`n" + $vm.Notes } else { $addnote } Set-VM -VM $vm -Notes $notes