Reputation: 85
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
Upvotes: 3
Views: 88
Reputation: 440471
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.
Upvotes: 5