3

I've got a very simple piece of code that is supposed to get the raw data I need to calculate number of seconds of CPU used in the last 30 seconds by any wscript process

$prev=Get-Process | Where-Object { $_.Name -eq "wscript" } 

$prev

start-sleep -Seconds 30

$curr=Get-Process | Where-Object { $_.Name -eq "wscript" } 

echo "section 2"

$prev

echo "section 3"

$curr

However, the values in $prev are getting reset after $curr as shown in the output below. Section 2 should be the same as the first section but it is matching the 3rd section.

Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName                                                                                                                                                       
-------  ------    -----      -----     ------     --  -- -----------                                                                                                                                                       
    177      19     2640       9252   1,795.55  12308   1 wscript                                                                                                                                                           
    177      19     2628       9340   1,799.67  17316   1 wscript                                                                                                                                                           
    177      19     2652       9292   1,803.83  25248   1 wscript                                                                                                                                                           
section 2
    177      19     2640       9252   1,825.28  12308   1 wscript                                                                                                                                                           
    177      19     2628       9340   1,829.42  17316   1 wscript                                                                                                                                                           
    177      19     2652       9292   1,833.53  25248   1 wscript                                                                                                                                                           
section 3
    177      19     2640       9204   1,825.28  12308   1 wscript                                                                                                                                                           
    177      19     2628       9296   1,829.42  17316   1 wscript                                                                                                                                                           
    177      19     2652       9264   1,833.55  25248   1 wscript

1 Answer 1

5

The [System.Diagnostics.Process] instances returned by Get-Process are live objects, which means that their properties reflect the process state at the time of invocation.[1]

So, assuming that the set of wscript processes hasn't changed between your Get-Process calls, you'll get objects that point to the same processes and their properties therefore return the same values - namely the then-current values, such as the CPU time consumed so far.

To avoid that, you need to take a snapshot of the values of interest, which is most easily done by creating [pscustomobject] clones of the process objects via Select-Object:

$prev = Get-Process -Name "wscript" | Select-Object *

Note that this clones all public properties; for better performance, you may want to just clone the values of interest with, say, Select-Object Id, Name, CPU.
Also, note how I've eliminated the need for Where-Object, given that you can simply find processes of a given name with Get-Process -Name.


To calculate the difference in CPU time consumed, you can then use the following approach:

# Get the processes...
$processes = Get-Process "wscript"
# ... and create snapshot objects for them.
$processesSnapshot = $processes | Select-Object *

start-sleep -Seconds 30

# Create objects that contain the delta (difference) in CPU
# time elapsed, by comparing the .CPU values from the live objects
# to that of the snapshots.
$i = 0
$CpuDeltas = foreach ($process in $processes) {
  $processSnapshot = $processesSnapshot[$i++]
  # Clone the snapshot object and add a property reflecting the CPU-consumption
  # delta and output it.
  $processSnapshot | Select-Object *, @{ n='CpuDelta'; e={ $process.CPU - $_.CPU } } 
}

# Output for display.
$CpuDeltas | Format-Table Id, Name, CpuDelta

[1] Some properties, such as .MainWindowTitle, are cached, and require a call to the .Refresh() method to reflect the then-current value.

Sign up to request clarification or add additional context in comments.

1 Comment

Glad to hear it, @dazedandconfused; my pleasure.

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.