package updates // applyScriptFor builds the Windows Update install script. It lives in a file // with no build tag so its content is tested on Linux: this module has no // Windows CI. // // Security-only keeps updates in the Security Updates or Critical Updates // classifications. Those two GUIDs are fixed by Microsoft and identical on // every Windows Update and WSUS server. func applyScriptFor(securityOnly bool) string { flag := "$false" if securityOnly { flag = "$true" } return "$SecurityOnly = " + flag + "\n" + applyScriptBody } const applyScriptBody = ` $ErrorActionPreference = 'Stop' $securityCats = @('0FA1201D-4330-4FA8-8AE9-B877473B6441', 'E6CF1350-C01B-414D-A61F-263D14D133B4') $session = New-Object -ComObject Microsoft.Update.Session $result = $session.CreateUpdateSearcher().Search("IsInstalled=0 and Type='Software' and IsHidden=0") $batch = New-Object -ComObject Microsoft.Update.UpdateColl foreach ($u in $result.Updates) { if ($u.InstallationBehavior.CanRequestUserInput) { continue } if ($SecurityOnly) { $isSec = $false foreach ($c in $u.Categories) { if ($securityCats -contains $c.CategoryID.ToUpper()) { $isSec = $true } } if (-not $isSec) { continue } } if (-not $u.EulaAccepted) { try { $u.AcceptEula() } catch { continue } } Write-Output ('selected: ' + $u.Title) $null = $batch.Add($u) } if ($batch.Count -eq 0) { Write-Output 'nothing-to-install'; exit 0 } $downloader = $session.CreateUpdateDownloader() $downloader.Updates = $batch $null = $downloader.Download() $installer = $session.CreateUpdateInstaller() $installer.Updates = $batch $r = $installer.Install() Write-Output ('resultcode=' + $r.ResultCode) # 2 = succeeded, 3 = succeeded with errors. Anything else failed, and this # process must exit non-zero so the agent reports a failure rather than an ack. if ($r.ResultCode -ne 2 -and $r.ResultCode -ne 3) { exit 1 } exit 0 `