Windows
banshee/windows-collection/windows/winrm/
updates
The updates waiting on a Windows, the critical ones, the restart required and the age of the last search, by WinRM and PowerShell
by banshee1 installation2 versions
v2Latest
Published on October 28, 2026. One naming convention across collections; documentation completed.
// The updates of a Windows, by WinRM: the updates waiting to be installed, the critical ones among them, a
// restart asked for by an installed update, and the age of the last successful search for updates.
// Runs one PowerShell script that only reads, through the Windows Update agent (the COM objects
// Microsoft.Update.Session, Microsoft.Update.SystemInfo and Microsoft.Update.AutoUpdate). The search is made
// offline: Windows answers from the result of its own last search, without asking Windows Update or the
// WSUS server. That result may be old: the age of the last search says how much the count is worth.
// The script is the one of windows/ssh/updates, without the powershell -Command "..." that cmd.exe needs
// there.
need('protocol:winrm');
output('pending', 'number', array('label' => 'Updates waiting'));
output('critical', 'number', array('label' => 'Critical updates waiting'));
output('reboot', 'text', array('label' => 'Restart required'));
output('search-age', 'number', array('label' => 'Last successful search', 'unit' => 'd'));
watch.above('critical-pending', 'Critical updates waiting', 'critical', array('warning' => 0));
watch.above('pending', 'Updates waiting', 'pending', array('enabled' => false));
watch.state('reboot-required', 'Restart required', 'reboot', array('warning' => array('yes')));
watch.above('search-old', 'No search for updates', 'search-age', array('warning' => 7, 'critical' => 30));
// MsrcSeverity is the rating Microsoft gives a security update: "Critical", "Important"...; it is the same
// whatever the language of Windows. LastSearchSuccessDate is in UTC; it comes out in hours, an integer.
// With $ErrorActionPreference set to Stop, a failed search ends the script with no answer, rather than an
// answer of zero updates.
$read = winrm.run("$ErrorActionPreference = 'Stop'; "
. "$searcher = (New-Object -ComObject Microsoft.Update.Session).CreateUpdateSearcher(); "
. "$searcher.Online = $false; "
. "$updates = @($searcher.Search('IsInstalled=0 and IsHidden=0').Updates); "
. "ConvertTo-Json -Compress -InputObject @{"
. "pending = $updates.Count; "
. "critical = @($updates | Where-Object MsrcSeverity -eq 'Critical').Count; "
. "reboot = (New-Object -ComObject Microsoft.Update.SystemInfo).RebootRequired; "
. "hours = [long]((Get-Date).ToUniversalTime()"
. " - (New-Object -ComObject Microsoft.Update.AutoUpdate).Results.LastSearchSuccessDate).TotalHours}");
$answer = text.trim($read['output']);
if (list.count(text.match($answer, '^\{')) == 0) {
fail('misconfigured', 'PowerShell did not return the state of Windows Update', $answer . $read['errors']);
}
$update = json.read($answer);
value('pending', $update['pending']);
value('critical', $update['critical']);
if ($update['reboot']) {
value('reboot', 'yes');
} else {
value('reboot', 'no');
}
value('search-age', number.round($update['hours'] / 24, 1));