I am trying to record CPU and memory utilizations of processes running in my window server using PowerShell. Script is running well but I am not getting anything if Mutiple process are running with same process name. it is throwing error: Method invocation failed because [System.Object[]] does not contain a method named 'op_Division I am getting my process list correctly using this command $processList = Get-Process -Name myMap | Select-Object -ExpandProperty ProcessName
Please help me, here is my code
$processList = Get-Process -Name myMap | Select-Object -ExpandProperty ProcessName
$outputFile = "D:\Users\vin\Performance_Srcipts\output\mymap.csv"
"Timestamp,ProcessName,%CPU,Memory(MB)" | Out-File -FilePath $outputFile
For ($i = 0; $i -lt 10; $i++) {
foreach ($processName in $processList) {
$process = Get-Process -Name $processName -ErrorAction SilentlyContinue
if ($process) {
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$cpu= try { (Get-Counter -Counter "\Process($processName*)\% Processor Time").CounterSamples.CookedValue / (Get-Process -Name $processName).Count } catch { 0 }
$memory = [math]::Round($process.WorkingSet64 / 1MB, 2)
"$timestamp,$processName,$cpu,$memory" | Out-File -FilePath $outputFile -Append
}
}
Start-Sleep -Seconds 5
}
Write-Host "Process monitoring completed. Data saved to $outputFile"
2 Answers 2
You already answered your question by yourself:
...but I am not getting anything if Mutiple process are running with same process name.
Also the error message itself shows [System.Object[]]. So, $process is an array of objects. You could change your code as follows:
For ($i = 0; $i -lt 10; $i++) {
foreach ($processName in $processList) {
$process = Get-Process -Name $processName -ErrorAction SilentlyContinue
if ($process.Count -gt 0) {
foreach ($p in $process) {
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$cpu = try {
(Get-Counter -Counter "\Process($processName*)\% Processor Time").
CounterSamples.CookedValue / (Get-Process -Name $processName).Count
}
catch { 0 }
$memory = [math]::Round($p.WorkingSet64 / 1MB, 2)
"$timestamp,$processName,$cpu,$memory" |
Out-File -FilePath $outputFile -Append
}
}
}
Start-Sleep -Seconds 5
}
Comments
Using the
-Nameparameter ofGet-Process- i.e. looking for processes by (executable) name - inherently means that it is possible for more than 1 process to match.Collecting the output from such a call matching multiple processes in a variable of necessity stores the process-information objects (of type
[System.Diagnostics.Process]) in an array (of type[object[]](in PowerShell terms) akaSystem.Object[](in .NET terms)).Performing property access such as
.WorkingSet64on such an array results in member-access enumeration, which means that the relevant property values of the array's elements are accessed and also returned as an array (in the case of two or more elements).Providing an array as an operator to
/, the division operator, isn't supported, which explains the error you saw; only scalar operands work.- In other words:
$process.WorkingSet64 / 1MBresulted in something like
@(42, 43) / 1MB, which predictably fails.
- In other words:
Here's a streamlined reformulation of your code that avoids the problem, by ensuring that $process only ever refers to a single process at a time:
$outputFile = 'D:\Users\vin\Performance_Srcipts\output\mymap.csv'
'Timestamp,ProcessName,%CPU,Memory(MB)' | Out-File -FilePath $outputFile
& {
for ($i = 0; $i -lt 10; $i++) {
foreach ($process in ($processes = Get-Process -ErrorAction SilentlyContinue -Name myMap)) {
$timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
$cpu = try { (Get-Counter -Counter "\Process($($process.Name)*)\% Processor Time").CounterSamples.CookedValue / $processes.Count } catch { 0 }
$memory = [math]::Round($process.WorkingSet64 / 1MB, 2)
"$timestamp,$processName,$cpu,$memory"
}
Start-Sleep -Seconds 5
}
} | Out-File -FilePath $outputFile -Append
Write-Host "Process monitoring completed. Data saved to $outputFile"
In general, mclayton's advice about using OO techniques in combination with Export-Csv to produce your CSV file is worth considering too.
$processis an array, so you must do something like$memory = [math]::Round($process[0].WorkingSet64 / 1MB, 2).Export-CsvorConvertTo-Csv.