banshee is under active development: collectors will keep changing, and a version you publish will likely need adjustments. For stable use, wait for version 1.0.0.

Windows

banshee/windows-collection/windows/ssh/

processes

The processes of a Windows: their number, and the instances, memory and processor time of each process followed, by SSH and PowerShell

  • windows
  • ssh
  • powershell
  • processes

by banshee1 installation2 versions

v2Latest

Published on October 28, 2026. One naming convention across collections; documentation completed.

Keen 1.0.0 · 60 lines
// The processes of a Windows, by SSH: their total number, and for each process name followed
// ("lsass.exe", "sqlservr.exe") the number of its instances, their memory and their processor time.
// Runs one PowerShell command that only reads Win32_Process: Name, ProcessId, WorkingSetSize (in bytes),
// KernelModeTime and UserModeTime (in hundreds of nanoseconds since the process started). A process that
// ends during the reading is simply missing from the answer.
need('protocol:ssh');

per('process', 'Processes', array('only' => array('lsass.exe', 'services.exe')));
output('processes', 'number', array('label' => 'Number of processes'));
output('instances', 'number', array('label' => 'Number of instances', 'per' => 'process'));
output('memory', 'number', array('label' => 'Memory', 'unit' => 'MiB', 'per' => 'process'));
output('cpu', 'number', array('label' => 'Processor time, as a share of one processor', 'unit' => '%', 'per' => 'process'));

watch.missing('missing', 'Process missing', 'instances', array('critical' => array('lsass.exe', 'services.exe')));
watch.above('too-many', 'Too many processes', 'processes', array('enabled' => false));
watch.above('memory-high', 'Memory of a process', 'memory', array('enabled' => false));
watch.above('cpu-high', 'Processor of a process', 'cpu', array('warning' => 90, 'for' => '3 runs', 'enabled' => false));

// A process name may hold characters outside ASCII: the output is written in UTF-8, without the byte order
// mark that the default UTF-8 encoding of .NET would put first.
$read = ssh.run("powershell -NoProfile -NonInteractive -Command \""
    . "[Console]::OutputEncoding = New-Object System.Text.UTF8Encoding; "
    . "ConvertTo-Json -Compress -InputObject @(Get-CimInstance Win32_Process"
    . " | Select-Object Name, ProcessId, WorkingSetSize, KernelModeTime, UserModeTime)\"");
$answer = text.trim($read['output']);
if (list.count(text.match($answer, '^\[')) == 0) {
    fail('misconfigured', 'PowerShell did not return the processes', $answer . $read['errors']);
}

// The instances of one name add up. Process 0, "System Idle Process", is not a process: its time is the
// idle time of the processors.
$processes = 0;
$count = array();
$memory = array();
$cpu = array();
foreach (json.read($answer) as $process) {
    if ($process['ProcessId'] == 0) {
        continue;
    }
    $name = $process['Name'];
    $processes = $processes + 1;
    $count[$name] = list.get($count, $name, 0) + 1;
    $memory[$name] = list.get($memory, $name, 0) + $process['WorkingSetSize'];
    $cpu[$name] = list.get($cpu, $name, 0) + $process['KernelModeTime'] + $process['UserModeTime'];
}
if ($processes == 0) {
    fail('misconfigured', 'No process found in Win32_Process', $answer);
}

value('processes', $processes);
foreach ($count as $name => $instances) {
    value('instances', $instances, $name);
    value('memory', number.round($memory[$name] / 1048576, 1), $name);
    // Ten million hundreds of nanoseconds a second are one processor: a hundred thousand are one percent.
    // Nothing at the first run, nor when an instance has ended and the sum went back.
    $rate = counter.rate('cpu', $cpu[$name], $name);
    if ($rate != '') {
        value('cpu', number.round($rate / 100000, 1), $name);
    }
}