I wanted to get the current CPU usage for certain processes, which appeared to be harder than I thought.
The Get-Process command will give you CPU time and program start time, but will not tell you when the CPU was being used by the process. Thus if you use the previous information you got from the tool to calculate the CPU usage, you’ll get the average CPU usage for that process since it started. (So if it started at 100% CPU usage and has been busy since, it’ll show as 100%, but when it’s software that’s been started days ago and just been using 100% for the past 10 minutes, without doing much the time before, it’ll show as the program using 0,05 % or something like that, since that is its average usage). If you’re interested in this information, Powershell.com explains how to do this. This is not the information I want to know, thus I started searching for another way to do it.
WMI has many possibilities, but most of my scripts that are lagging, are lagging because of WMI usage, thus I try to use this only if I can’t find another way to do so.
I finally got to the Get-Counter command, which gets information from Performance Counters. I’d like to get % processor time information, thus I’ll check this with the following command (add the * to get all instances of the process):
Get-Counter "\Process(Chrome*)\% Processor Time"
This gives me a list of all process instances and their current CPU usage.
If you’d want to take multiple samples, this can also be specified (just like the sample interval)
Get-Counter "\Process(Chrome*)\% Processor Time" -SampleInterval 1 -MaxSamples 5
At the moment I’m only interested in getting 1 quick sample (this script will be integrated in a monitoring tool), thus I’ll skip these switches. But to explain them: The SampleInterval switch will set the interval time between the 2 measuring samples, default is 1 second, the MaxSamples switch will give you an x amount of samples; the default value is 1 sample.
The output is not quite what I want, I only like to get the CounterSamples. This is achieved with this command:
(Get-Counter "\Process(Chrome*)\% Processor Time").CounterSamples
This’ll give me this output (with a lot of open tabs in chrome):
But now, there’s the problem that the name as being used in the Performance Counters isn’t the same as in the process list, neither do I know a process ID. Lets solve this with the Get-Counter command as well. This command will show me the Process ID’s:
(Get-Counter "\Process(Chrome*)\ID Process").CounterSamples
And will give me this list of ID’s:
Now it’s time to start working with the data. I’ll start by putting the data in variables, then I’ll check if the lists are the same size. Once that’s done, I’ll store the data that I want and return the list sorted with the process with the highest CPU usage on top:
Param([parameter(Mandatory=$True)][string]$Process) $ProcessId = (Get-Counter "\Process($Process*)\ID Process").CounterSamples | Sort-Object Path $ProcessCPU = (Get-Counter "\Process($Process*)\% Processor Time").CounterSamples | Sort-Object Path,CPU $TotalInfo = @()
If($ProcessId.Count -eq $ProcessCPU.Count)
{ For($i = 0; $i -lt $ProcessId.Count; $i++) { $TempInfo = $ProcessId[$i].Path.Split("\")[3].Substring($ProcessId[$i].Path.Split("\")[3].IndexOf("(") + 1) $TempInfo = $TempInfo.Substring(0,$TempInfo.IndexOf(")")) $ProcessInfo = New-Object psobject Add-Member -InputObject $ProcessInfo -MemberType noteproperty -Name "CounterName" -Value $TempInfo -Force Add-Member -InputObject $ProcessInfo -MemberType noteproperty -Name "Id" -Value $ProcessId[$i].CookedValue -Force Add-Member -InputObject $ProcessInfo -MemberType noteproperty -Name "Cpu" -Value $ProcessCPU[$i].CookedValue -Force $TotalInfo += $ProcessInfo } } Return $TotalInfo | Sort-Object Cpu -Descending
And this will give me a nice list like this:
Oh, if you’re interested in getting the total CPU load of a system, this is also pretty easy with the Get-Counter command. Powershell.com also describes this, but can be done with this command:
(Get-Counter '\processor(_total)\% processor time').CounterSamples
The script can be downloaded here.
This script is perfect! Thanks so much for posting this!!
LikeLike
You’re welcome! Thanks for your reply.
LikeLike
Hi,
I’m running this script to get CPU Utilization of a process, but I’m not able to store that % in a variable. At last I need to print that message as “Process XYZ is using N % of CPU”
$ProcessName = “explorer”
#$ProcessName = (Get-Process -Id $ProcessPID).Name
$CpuCores = (Get-WMIObject Win32_ComputerSystem).NumberOfLogicalProcessors
$Samples = (Get-Counter “\Process($Processname*)\% Processor Time”).CounterSamples
$Samples | Select `
InstanceName,
@{Name=”CPU %”;Expression={[Decimal]::Round(($_.CookedValue / $CpuCores), 2)}}
I’m very new to shell scripting, please help.
LikeLike
You’ve already got it in a variable. In the bottom line (starting with $Samples) is where it’s stored. If you recall $Samples.CookedValue that’s the cpu usage that’s stored in your variable.
LikeLiked by 1 person