使用 Powershell 的 CPU% 和进程 ID 的前 5 个进程

Top 5 Processes with CPU % and Process ID using Powershell

我试过这个脚本

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}
     }

我能够获取 ProcessName 和 CPU % 列,但不能获取 ProcessID

ProcessName  CPU   ProcessId
-----------  ---   ---------
firefox#4    0.58%
svchost#11   0.19%
firefox#6    0.19%
dwm          0.10%
svchost#39   0.10%

确保从每个计数器实例请求 % Processor Time ID Process 计数器,然后使用 Group-Object 将它们组合在一起。

值得注意的是,您不需要正则表达式 来关联两者,只需在计数器路径的第一部分 (\Process(notepad#3)) 上分组即可。正则表达式也 不需要 来提取进程名称,因为每个样本已经有一个 InstanceName 属性 和相应的进程名称。

关联名称+进程ID+样本值后,就可以开始排序,最后格式化CPU百分比:

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
  }