Active Directory
banshee/active-directory-collection/active-directory/winrm/
gpo
The Group Policy processing errors written to the System log since the previous run, by WinRM and PowerShell
par banshee1 installation2 versions
v2Dernière
Publiée le 28 octobre 2026. One naming convention across collections; documentation completed.
// The errors of Group Policy processing written to the System log of a Windows since the previous run, by
// WinRM: their number, and their event identifiers. Its watch is checked by default, a warning: a policy that
// does not apply is what this collector is for. Some of these errors are transient (a domain controller not
// reached at startup): the threshold is raised on the probe once the usual rate is known.
// Runs PowerShell scripts that only read the log, by Get-WinEvent, as windows/winrm/eventlog of
// banshee/windows-collection does: the collector keeps in the cache of the probe the highest record number
// it has counted, and counts at the next run the errors (Level 2) of the provider Microsoft-Windows-GroupPolicy
// above it. The first run only notes the number where counting starts.
// The scripts are those of active-directory/ssh/gpo, without the powershell -Command "..." that cmd.exe needs
// there.
need('protocol:winrm');
output('errors', 'number', array('label' => 'Group Policy errors since the previous run'));
output('events', 'text', array('label' => 'Their event identifiers'));
watch.above('errors', 'Group Policy errors', 'errors', array('warning' => 0));
// The number kept lasts a week: a probe stopped longer starts again as at its first run.
if (!cache.has('last-record')) {
$read = winrm.run("(Get-WinEvent -LogName System -MaxEvents 1).RecordId");
$newest = text.trim($read['output']);
if (!text.is_number($newest)) {
fail('misconfigured', 'PowerShell did not return the last record of the System log', $newest . $read['errors']);
}
// Kept as a number, to be compared with the numbers of the next run.
cache.set('last-record', $newest + 0, 604800);
skip('First reading: errors are counted from the next run');
}
$last = cache.get('last-record');
// newest: the record number of the latest event of the log, of any provider and level; last: the highest
// record number among the errors read, 0 when there is none. Get-WinEvent reports "no event found" as an
// error, silenced on the reading of the errors; with $ErrorActionPreference set to Stop, any other failure, an
// access to the log refused among them, ends the script on the reading of the newest event, with no answer,
// rather than an answer of zero errors.
$read = winrm.run("$ErrorActionPreference = 'Stop'; "
. "$events = @(Get-WinEvent -LogName System -ErrorAction SilentlyContinue"
. " -FilterXPath '*[System[Provider[@Name=''Microsoft-Windows-GroupPolicy''] and Level=2 and EventRecordID>" . $last . "]]'); "
. "ConvertTo-Json -Compress -InputObject @{"
. "newest = [long](Get-WinEvent -LogName System -MaxEvents 1).RecordId; "
. "last = [long]($events | Measure-Object RecordId -Maximum).Maximum; "
. "errors = $events.Count; "
. "ids = (@($events | Select-Object -ExpandProperty Id -Unique) -join ', ')}");
$answer = text.trim($read['output']);
if (list.count(text.match($answer, '^\{')) == 0) {
fail('misconfigured', 'PowerShell did not return the Group Policy errors of the System log', $answer . $read['errors']);
}
$log = json.read($answer);
// A log that was cleared numbers its events from 1 again: counting starts again from the start of the log.
if ($log['newest'] < $last) {
cache.set('last-record', 0, 604800);
skip('The System log was cleared: errors are counted again from the next run');
}
if ($log['last'] > $last) {
cache.set('last-record', $log['last'], 604800);
} else {
cache.set('last-record', $last, 604800);
}
value('errors', $log['errors']);
value('events', $log['ids']);