I tried this script
Get-Counter -ErrorAction SilentlyContinue '\Process(*)\% Processor Time' |
Select -ExpandProperty countersamples |
?{$_.instanceName -notmatch "^(idle|_total|system)$"} |
Sort -Descending cookedvalue |
Select -First 5 @{
L='ProcessName';
E={[regex]::matches($_.Path,'.*process\((.*)\)\\% processor.*').groups[1].value}
},
@{
L='CPU';
E={($_.Cookedvalue/100/$env:NUMBER_OF_PROCESSORS).toString('P')}
},
@{
L='ProcessId';
E={((Get-Counter "\Process([regex]::matches($_.Path,'.*process\((.*)\)\\% processor.*').groups[1].value)\ID Process" -ErrorAction SilentlyContinue).CounterSamples).Cookedvalue}
}
I am able to get ProcessName and CPU % columns but not ProcessID
ProcessName CPU ProcessId
----------- --- ---------
firefox#4 0.58%
svchost#11 0.19%
firefox#6 0.19%
dwm 0.10%
svchost#39 0.10%
CodePudding user response:
Make sure you request both the % Processor Time
and ID Process
counter from each counter instance, then use Group-Object
to group them together.
Worth noting is that you don't need regex to correlate the two, simply group on the first part of the counter path (\Process(notepad#3)
). Regex is also not needed for extracting the process name, since each sample already has an InstanceName
property with the corresponding process name.
Once you've correlated name process ID sample value, you can start sorting, and then finally format the CPU percentage:
Get-Counter '\Process(*)\ID Process','\Process(*)\% Processor Time' -ErrorAction SilentlyContinue |
ForEach-Object {
$_.CounterSamples |
Where-Object InstanceName -NotMatch '^(?:idle|_total|system)$' |
Group-Object {Split-Path $_.Path} |
ForEach-Object {
[pscustomobject]@{
ProcessName = $_.Group[0].InstanceName
ProcessId = $_.Group |? Path -like '*\ID Process' |% RawValue
CPUCooked = $_.Group |? Path -like '*\% Processor Time' |% CookedValue
}
} |Sort-Object CPUCooked -Descending |
Select-Object -First 5 -Property *,@{Name='CPUPercentage';Expression={'{0:P}' -f ($_.CPUCooked / 100 / $env:NUMBER_OF_PROCESSORS)}} -ExcludeProperty CPUCooked
}