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

多实例进程场景下PowerShell监控脚本报错求助(op_Division缺失)

解决PowerShell多实例进程CPU/内存监控脚本报错问题

问题描述

在Windows Server上用PowerShell脚本记录指定进程的CPU和内存使用率时,单实例进程场景运行正常,但存在同名多实例进程时,脚本无输出且抛出错误:

Method invocation failed because [System.Object[]] does not contain a method named 'op_Division'

已确认$processList = Get-Process -Name myMap | Select-Object -ExpandProperty ProcessName能正确获取进程列表。

错误原因

  1. CPU计算逻辑问题:当进程存在多实例时,Get-Counter "\Process($processName*)\% Processor Time"返回的CookedValue是数组,直接对数组执行除法操作(除以进程数)会触发类型错误,因为PowerShell不支持数组与数字的直接除法运算。
  2. 内存计算逻辑问题:多实例场景下,Get-Process -Name $processName返回的是进程对象数组,$process.WorkingSet64会返回所有实例的内存值数组,直接做除法得到的也是数组,无法正确写入CSV。

修复方案

方案1:汇总多实例进程的CPU和总内存(按进程名统计)

修改脚本中的CPU和内存计算逻辑,处理数组对象:

$processList = Get-Process -Name myMap | Select-Object -ExpandProperty ProcessName | Get-Unique

$outputFile = "D:\Users\vin\Performance_Srcipts\output\mymap.csv"

# 写入CSV表头
"Timestamp,ProcessName,%CPU,TotalMemory(MB)" | Out-File -FilePath $outputFile -Encoding UTF8

For ($i = 0; $i -lt 10; $i++) { 
    foreach ($processName in $processList) {
        # 一次性获取所有实例,避免重复调用
        $processes = Get-Process -Name $processName -ErrorAction SilentlyContinue
 
        if ($processes) {
            $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
            $processCount = $processes.Count
            
            # 处理CPU统计:先获取所有实例的CPU值,求和后除以进程数
            $cpuValues = try { 
                (Get-Counter -Counter "\Process($processName*)\% Processor Time").CounterSamples.CookedValue 
            } catch { 
                @(0)
            }
            $totalCpu = ($cpuValues | Measure-Object -Sum).Sum
            $avgCpu = [math]::Round($totalCpu / $processCount, 2)

            # 处理内存统计:汇总所有实例的内存
            $totalMemory = ($processes.WorkingSet64 | Measure-Object -Sum).Sum
            $totalMemoryMB = [math]::Round($totalMemory / 1MB, 2)

            # 写入CSV
            "$timestamp,$processName,$avgCpu,$totalMemoryMB" | Out-File -FilePath $outputFile -Append -Encoding UTF8
        }
    }
    Start-Sleep -Seconds 5 
}

Write-Host "Process monitoring completed. Data saved to $outputFile"

方案2:单独记录每个进程实例的CPU和内存(按实例统计)

如果需要监控每个实例的单独数据,修改遍历逻辑:

$processName = "myMap" # 直接指定进程名,无需提前获取列表
$outputFile = "D:\Users\vin\Performance_Srcipts\output\mymap.csv"

# 写入CSV表头,增加PID区分实例
"Timestamp,ProcessName,PID,%CPU,Memory(MB)" | Out-File -FilePath $outputFile -Encoding UTF8

For ($i = 0; $i -lt 10; $i++) { 
    $processes = Get-Process -Name $processName -ErrorAction SilentlyContinue
 
    if ($processes) {
        $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
        # 获取所有实例的CPU计数器
        $cpuCounters = try { 
            Get-Counter -Counter "\Process($processName*)\% Processor Time" | Select-Object -ExpandProperty CounterSamples
        } catch { 
            @()
        }

        foreach ($proc in $processes) {
            # 匹配当前进程实例的CPU值(通过计数器实例名匹配,格式为"myMap#1"、"myMap#2")
            $counterInstance = "$processName#$($proc.Id)"
            $cpuValue = ($cpuCounters | Where-Object { $_.InstanceName -eq $counterInstance }).CookedValue
            $cpu = if ($cpuValue) { [math]::Round($cpuValue, 2) } else { 0 }
            
            $memoryMB = [math]::Round($proc.WorkingSet64 / 1MB, 2)
            # 写入每个实例的数据
            "$timestamp,$processName,$($proc.Id),$cpu,$memoryMB" | Out-File -FilePath $outputFile -Append -Encoding UTF8
        }
    }
    Start-Sleep -Seconds 5 
}

Write-Host "Process monitoring completed. Data saved to $outputFile"

关键修改说明

  • 对Get-Counter返回的数组值,先用Measure-Object -Sum求和,再做除法运算,避免直接操作数组。
  • 多实例场景下,一次性获取所有进程对象,减少重复调用Get-Process提升效率。
  • 方案2中通过进程ID匹配对应的CPU计数器实例,确保每个进程的CPU值对应正确。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 19:53:19