Last Update: Sep 04, 2024 | Published: Nov 18, 2015
The last few PowerShell Problem Solver articles have involved getting processor load or utilization information with WMI and PowerShell. If you’re just jumping in with us, you should get caught up because I am going to build on what’s been outlined in previous articles in this series. The original question consisted of two different parts, where the first part was to get average processor load values. The second part looks to find the top five processes that are consuming the most processor time. Let’s look at this task. Each method I’ll demonstrate expresses processor time in a slightly different manner and they may not indicate which processes are consuming the most CPU time at the time you are querying.
Processor Load Article Series:
The Get-Process cmdlet is easy enough to use and the results include a CPU property. You can use common cmdlets to sort and select the top five processes.
I ran this command locally. The CPU property is actually a calculated property that PowerShell brings to the party. If you research the System.Diagnostics.Process class, you won't see CPU listed. The CPU property is defined as the TotalSeconds property of the TotalProcessTime property. If you prefer, you can select this property directly.
Some processes are protected, which is why you'll see an error. I should also point out that this value indicates a historical figure and is not representative of what might be using the CPU right now. But let's carry on and query some remote computers. There is no value for CPU which means TotalProcessorTime probably is empty as well. It turns out that you cannot get this value through a remote query. You have to run Get-Process locally. This means we need to use PowerShell remoting.
This actually works to our advantage when we want to query multiple computers.
But what if that isn't the CPU value you were hoping for?Using WMI
Another option is to use WMI. Although there is a Win32_Process class, it doesn't contain any processor related properties. There are WMI performance classes, specifically Win32_PerfFormattedData_PerfProc_Process and Win32_PerfRawData_PerfProc_Process. These classes have a property called PercentProcessorTime, which is the percentage of time that all process threads took to complete. This is similar to what we saw with Get-Process. The raw data is in 100 nano second intervals. In my testing, the cooked values which you can see with the PerfFormattedData version always returns 0, so I'll use the raw data.
Get-WmiObject Win32_PerfRawData_PerfProc_Process -filter "Name '_Total' and Name 'Idle'" -computername chi-dc04 | Sort PercentProcessorTime -descending | Select -first 5 Name,PercentProcessorTime,IDProcess,PSComputername | format-table –auto
Note that I am filtering with WMI and not using Where-Object. If you need to filter in PowerShell, filter as early in your expression as you can.
Again, for performance reasons, using remoting is helpful when querying multiple computers.
If you prefer to format the percent value yourself you can try something like this:
As you have probably realized if you have made it this far, this is not beginner stuff. I still want to show you how to use performance counters to get process information but that is going to be equally complex, so I will save that for the next article.