PowerShell脚本报错op_Addition方法未找到,求解决方案
[System.Object[]]不包含op_Addition方法报错 问题场景
有一个PowerShell脚本在其他电脑可正常运行,仅单台电脑出现如下报错:
调用方法失败,因为[System.Object[]]不包含名为“op_Addition”的方法。
报错位置:C:\Users\stream1\Desktop\watchdog.ps1:8 字符:5
对应代码行:$wmi += (Get-WMIObject -Class Win32_PerfFormattedData_Tcpip_Netwo ...
错误类别信息:CategoryInfo : InvalidOperation: (op_Addition:String) [], RuntimeException
完全限定错误ID:FullyQualifiedErrorId : MethodNotFound
脚本代码如下:
#$ErrorActionPreference = 'SilentlyContinue' $threshold = 6000 $timer = new-timespan -Seconds 10 $wmi = 0 $count = 0 $clock = [diagnostics.stopwatch]::StartNew() while ($clock.elapsed -lt $timer){ $wmi += (Get-WMIObject -Class Win32_PerfFormattedData_Tcpip_NetworkInterface | Select-Object BytesSentPerSec).BytesSentPerSec $count++ } $kbytes = ($wmi/$count) / 1kb * 8 #to kbit/s if($kbytes -le $threshold) { Write-Output $kbytes Write-Host "Neustart" taskkill /f /im obs64.exe timeout /t 5 Start-Process -FilePath "obs64.exe" -WorkingDirectory "C:\Program Files\obs-studio\bin\64bit\" --startstreaming --minimize-to-tray } else { Write-Output $kbytes Write-Host "Alles OK" }
原因分析
问题核心是$wmi的类型意外转换:
- 初始
$wmi = 0为数值类型 - 报错的电脑存在多个网络适配器,
Get-WMIObject返回多个网卡对象,.BytesSentPerSec会生成一个数组(System.Object[]) - 第一次执行
$wmi += 数组时,PowerShell会自动将$wmi转换为数组类型 - 后续循环再执行
$wmi += 数组时,会尝试对两个数组执行加法操作,但PowerShell数组不支持这种直接加法,因此抛出op_Addition方法不存在的错误
解决办法
方案1:累加单轮网卡发送量总和
每次获取网卡数据后,先计算所有网卡的BytesSentPerSec总和,再将数值累加到$wmi中,避免类型转换问题:
#$ErrorActionPreference = 'SilentlyContinue' $threshold = 6000 $timer = new-timespan -Seconds 10 $wmi = 0 $count = 0 $clock = [diagnostics.stopwatch]::StartNew() while ($clock.elapsed -lt $timer){ # 计算当前所有网卡的BytesSentPerSec总和 $currentTotal = (Get-WMIObject -Class Win32_PerfFormattedData_Tcpip_NetworkInterface | Select-Object -ExpandProperty BytesSentPerSec) | Measure-Object -Sum | Select-Object -ExpandProperty Sum $wmi += $currentTotal $count++ } $kbytes = ($wmi/$count) / 1kb * 8 #to kbit/s if($kbytes -le $threshold) { Write-Output $kbytes Write-Host "Neustart" taskkill /f /im obs64.exe timeout /t 5 Start-Process -FilePath "obs64.exe" -WorkingDirectory "C:\Program Files\obs-studio\bin\64bit\" --startstreaming --minimize-to-tray } else { Write-Output $kbytes Write-Host "Alles OK" }
方案2:初始化为数组,最后统一求和
如果需要保留每轮的原始数据,可以将$wmi初始化为空数组,最后再计算所有数据的总和:
#$ErrorActionPreference = 'SilentlyContinue' $threshold = 6000 $timer = new-timespan -Seconds 10 $wmi = @() # 初始化为空数组 $count = 0 $clock = [diagnostics.stopwatch]::StartNew() while ($clock.elapsed -lt $timer){ # 将每轮的网卡数据添加到数组中 $wmi += (Get-WMIObject -Class Win32_PerfFormattedData_Tcpip_NetworkInterface | Select-Object -ExpandProperty BytesSentPerSec) $count++ } # 计算所有数据的总和,再求平均值 $totalBytes = $wmi | Measure-Object -Sum | Select-Object -ExpandProperty Sum $kbytes = ($totalBytes/$count) / 1kb * 8 #to kbit/s if($kbytes -le $threshold) { Write-Output $kbytes Write-Host "Neustart" taskkill /f /im obs64.exe timeout /t 5 Start-Process -FilePath "obs64.exe" -WorkingDirectory "C:\Program Files\obs-studio\bin\64bit\" --startstreaming --minimize-to-tray } else { Write-Output $kbytes Write-Host "Alles OK" }
额外优化建议
Get-WMIObject已被PowerShell官方弃用,建议替换为更兼容高效的Get-CimInstance:
将Get-WMIObject -Class Win32_PerfFormattedData_Tcpip_NetworkInterface替换为Get-CimInstance -ClassName Win32_PerfFormattedData_Tcpip_NetworkInterface
内容的提问来源于stack exchange,提问作者Thomas Geers

