0

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
  • 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[]]. $process is an array, so you must do something like $memory = [math]::Round($process[0].WorkingSet64 / 1MB, 2). Commented Jun 29 at 13:18
  • 1
    Note - it would be an incredibly pathological edge case but if a process name has a comma in it your remaining data for that row will be thrown out by one column. When generating formatted data it’s a good idea to use pre-built cmdlets like Export-Csv or ConvertTo-Csv. Commented Jun 29 at 19:59

2 Answers 2

0

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 
}
Sign up to request clarification or add additional context in comments.

Comments

0
  • Using the -Name parameter of Get-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) aka System.Object[] (in .NET terms)).

  • Performing property access such as .WorkingSet64 on 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 / 1MB resulted in something like
      @(42, 43) / 1MB, which predictably fails.

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.