# install_updates.ps1 — aplică update-urile Windows pe VM 109, controlat. # # Rulat exclusiv din vm109-patch-window.sh (fereastra lunară de patching). # În restul timpului VM 109 are NoAutoUpdate=1, ca Windows Update să nu mai # poată porni singur în timpul testului DR săptămânal (incident 2026-08-08). # # Folosește API-ul COM Microsoft.Update.Session — funcționează într-o sesiune # SSH non-interactivă, spre deosebire de UsoClient care raportează asincron și # nu întoarce niciun status utilizabil. # # Ieșire (linii parsabile din bash): # FOUND= # INSTALLED= # FAILED= # REBOOT_REQUIRED= # RESULT= $ErrorActionPreference = "Stop" try { $session = New-Object -ComObject Microsoft.Update.Session $searcher = $session.CreateUpdateSearcher() Write-Output "Searching for updates..." $result = $searcher.Search("IsInstalled=0 AND IsHidden=0") Write-Output ("FOUND=" + $result.Updates.Count) if ($result.Updates.Count -eq 0) { Write-Output "INSTALLED=0" Write-Output "FAILED=0" Write-Output "REBOOT_REQUIRED=false" Write-Output "RESULT=NO_UPDATES" exit 0 } $toInstall = New-Object -ComObject Microsoft.Update.UpdateColl foreach ($u in $result.Updates) { if ($u.EulaAccepted -eq $false) { $u.AcceptEula() } Write-Output (" + " + $u.Title) $toInstall.Add($u) | Out-Null } Write-Output "Downloading..." $downloader = $session.CreateUpdateDownloader() $downloader.Updates = $toInstall $downloader.Download() | Out-Null $ready = New-Object -ComObject Microsoft.Update.UpdateColl foreach ($u in $toInstall) { if ($u.IsDownloaded) { $ready.Add($u) | Out-Null } } if ($ready.Count -eq 0) { Write-Output "INSTALLED=0" Write-Output "FAILED=0" Write-Output "REBOOT_REQUIRED=false" Write-Output "RESULT=ERROR" exit 1 } Write-Output "Installing..." $installer = $session.CreateUpdateInstaller() $installer.Updates = $ready $installResult = $installer.Install() # ResultCode: 2 = succeeded, 3 = succeeded with errors, restul = eșec. $ok = 0 $ko = 0 for ($i = 0; $i -lt $ready.Count; $i++) { $code = $installResult.GetUpdateResult($i).ResultCode if ($code -eq 2 -or $code -eq 3) { $ok++ } else { $ko++ } } Write-Output ("INSTALLED=" + $ok) Write-Output ("FAILED=" + $ko) Write-Output ("REBOOT_REQUIRED=" + $installResult.RebootRequired.ToString().ToLower()) if ($ko -gt 0) { Write-Output "RESULT=ERROR"; exit 1 } Write-Output "RESULT=OK" exit 0 } catch { Write-Output ("ERROR: " + $_.Exception.Message) Write-Output "RESULT=ERROR" exit 1 }