Have a complaint from a user that a server is sluggish? Maybe you’re just curious if the problem you’re seeing on a server is related to a process consuming a lot of CPU, or you know the CPU is pegged and you want to identify which process is the culprit.
I had a similar situation, and so I wrapped it up into a nice little package that I’ll share with you here. This uses WMI to find processes running high CPU with PowerShell.
It can run in one of two ways – by reporting all processes using more than a certain percentage of the CPU or by reporting a the top CPU hogging processes. I use parameter sets for those different options, so it’s one or the other. I considered making it possible to list “top 3 processes consuming more than 10%,” which could have been done very easily, but decided I preferred it this way.
Function Get-iLPHighCPUProcess { <# .SYNOPSIS Retrieve processes that are utilizing the CPU on local or remote systems. .DESCRIPTION Uses WMI to retrieve process information from remote or local machines. You can specify to return X number of the top CPU consuming processes or to return all processes using more than a certain percentage of the CPU. .EXAMPLE Get-HighCPUProcess Returns the 3 highest CPU consuming processes on the local system. .EXAMPLE Get-HighCPUProcess -Count 1 -Computername AppServer01 Returns the 1 highest CPU consuming processes on the remote system AppServer01. .EXAMPLE Get-HighCPUProcess -MinPercent 15 -Computername "WebServer15","WebServer16" Returns all processes that are consuming more that 15% of the CPU process on the hosts webserver15 and webserver160 #> [Cmdletbinding(DefaultParameterSetName="ByCount")] Param( [Parameter(ValueFromPipelineByPropertyName)] [Alias("PSComputername")] [string[]]$Computername = "localhost", [Parameter(ParameterSetName="ByPercent")] [ValidateRange(1,100)] [int]$MinPercent, [Parameter(ParameterSetName="ByCount")] [int]$Count = 3 ) Process { Foreach ($computer in $Computername){ Write-Verbose "Retrieving processes from $computer" $wmiProcs = Get-WmiObject Win32_PerfFormattedData_PerfProc_Process -Filter "idProcess != 0" -ComputerName $Computername if ($PSCmdlet.ParameterSetName -eq "ByCount") { $wmiObjects = $wmiProcs | Sort PercentProcessorTime -Descending | Select -First $Count } elseif ($psCmdlet.ParameterSetName -eq "ByPercent") { $wmiObjects = $wmiProcs | Where {$_.PercentProcessorTime -ge $MinPercent} } #end IF $wmiObjects | Foreach { $outObject = [PSCustomObject]@{ Computername = $computer ProcessName = $_.name Percent = $_.PercentProcessorTime ID = $_.idProcess } $outObject } #End ForeachObject } #End ForeachComputer } }
Things I like about this function are:
- Concise output: Computername, ProcessName, Percent (of CPU), and ID (Process ID)
- Accepts pipeline input by property value of “ComputerName” or “PSComputerName”
- Easy to use against multiple computers
- Flexible: I like the option to find the 3 highest CPU processes or all processes above 5 percent (or any percent)
- Accepts multiple computers through parameter (as an array) or through the pipeline
Questions? Comments? Whether it’s a different approach or just saying “Thanks” I really appreciate the feedback.