You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell提取CPU进程使用率:结果与任务管理器不符求验证

解决PowerShell提取CPU使用率与任务管理器差异的问题

我来帮你拆解下问题所在,以及更准确的解决方案:

为什么之前的命令会和任务管理器结果不一致?

  • Get-WmiObject Win32_Process/Get-Process的局限:这两个命令返回的CPU属性是进程从启动到现在的累计CPU时间(秒),不是实时的使用率,所以你没法直接拿到当前的CPU占用率,这也是你觉得“未成功”的核心原因。
  • 第一个Get-Counter命令的问题:\Process(*)\% Processor Time计数器的CookedValue代表的是进程在采样间隔内占用的所有逻辑CPU的总时间百分比——比如8核CPU上,一个占满1核的进程会返回100,但任务管理器会显示12.5%(1/8)。你直接除以100转百分比,相当于把总核心的占用当成了单核心的,自然和任务管理器差很多。
  • 第二个命令的逻辑是对的,但动态数值验证的问题:你已经考虑了除以逻辑核心数,但Get-Counter是单次采样的平均值,任务管理器也是动态刷新(默认1秒),所以数值会实时变化。验证时可以固定采样间隔,或者和任务管理器“详细信息”页的CPU列对比(这个列就是除以核心数后的结果)。

更准确的PowerShell实现(和任务管理器对齐)

要得到和任务管理器几乎一致的结果,最好的方式是两次采样计算CPU时间增量,因为单次采样的计数器值可能受采样间隔影响,增量计算更贴合任务管理器的逻辑:

# 获取逻辑核心总数
$coreCount = (Get-WmiObject Win32_Processor | Measure-Object -Sum NumberOfLogicalProcessors).Sum

# 第一次采样
$sample1 = Get-Counter '\Process(*)\% Processor Time'
Start-Sleep -Milliseconds 1000  # 和任务管理器默认刷新间隔保持一致

# 第二次采样
$sample2 = Get-Counter '\Process(*)\% Processor Time'

# 计算每个进程的CPU使用率(和任务管理器对齐)
$results = Compare-Object $sample1.CounterSamples $sample2.CounterSamples -Property InstanceName, CookedValue -PassThru |
    Group-Object InstanceName |
    ForEach-Object {
        $delta = $_.Group | Where-Object SideIndicator -eq '=>' | Select-Object -ExpandProperty CookedValue -First 1
        [PSCustomObject]@{
            ProcessName = $_.Name
            'CPU %' = [Math]::Round($delta / $coreCount, 1)
        }
    } |
    Where-Object 'CPU %' -gt 0 |
    Sort-Object 'CPU %' -Descending

# 格式化输出
$results | Format-Table ProcessName, 'CPU %' -AutoSize

用Get-Process实现实时使用率的另一种方式

如果你想用Get-Process,可以通过计算两次采样的CPU时间差来得到使用率:

$coreCount = (Get-WmiObject Win32_Processor | Measure-Object -Sum NumberOfLogicalProcessors).Sum
$proc1 = Get-Process | Select-Object Name, Id, CPU
Start-Sleep -Seconds 1
$proc2 = Get-Process | Select-Object Name, Id, CPU

$usage = Compare-Object $proc1 $proc2 -Property Name, Id, CPU -PassThru |
    Group-Object Id |
    ForEach-Object {
        $prevCPU = $_.Group | Where-Object SideIndicator -eq '<=' | Select-Object -ExpandProperty CPU -First 1
        $currCPU = $_.Group | Where-Object SideIndicator -eq '=>' | Select-Object -ExpandProperty CPU -First 1
        if ($prevCPU -ne $null -and $currCPU -ne $null) {
            $delta = $currCPU - $prevCPU
            [PSCustomObject]@{
                ProcessName = $_.Group[0].Name
                'CPU %' = [Math]::Round(($delta / 1) / $coreCount * 100, 1)
            }
        }
    } |
    Where-Object 'CPU %' -gt 0 |
    Sort-Object 'CPU %' -Descending

$usage | Format-Table ProcessName, 'CPU %' -AutoSize

验证小技巧

  • 打开任务管理器的“详细信息”页,查看CPU列(这个列就是除以核心数后的百分比),和PowerShell的输出对比。
  • 可以找一个占用率稳定的进程(比如打开一个CPU密集型程序),对比两边的数值,差异会非常小。

内容的提问来源于stack exchange,提问作者SQLDoctor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 10:12:51