lørdag 26. oktober 2013

PowerShell: List processes currently using the most CPU

If you find yourself supporting users on Remote Desktop Session Host servers, you may want to use PowerShell to identify processes with high CPU utilization and also kill such processes if they cause problem for other users.

I have created a small PowerShell script that will help with this task. Save the script on your Session Host servers, and use PowerShell from your Workstation to invoke it.

You have to enable PowerShell Remoting on your Session Host servers to allow it, like this:
Enable-PSRemoting -Force

You should also allow unsigned scripts to be executed, like this:
Set-ExecutionPolicy RemoteSigned

If your Workstation is not in the same domain, you must tell your Workstation to trust the Remote host, like this:
Set-Item wsman:\localhost\client\trustedhosts *

This will trust all Remote hosts, but you can also specify hosts with a comma-separated list of hostnames.

To run the command on the session host, you can enter a remote PowerShell session, where you can run multiple commands, like this:
Enter-PSSession -ComputerName

To exit a Remote PowerShell session you simply type exit.

You can also use Invoke-Command, instead of Enter-PSSession, if you only need to run one command.

Now then, if you save the script as D:\Scripts\PSGetTop.ps1 on a server called, you would start PowerShell on your Workstation, and type (this will use your current credentials, so you would need to have permission, like local administrator, on that server to do this):
Enter-PSSession -ComputerName
CD D:\Scripts
# List top 5 processes with highest CPU utilization:

# List top 10 processes with highest CPU utilization:
.\PSGetTop.ps1 -ReturnCount 10

# List the WINWORD process with highest CPU utilization:
.\PSGetTop.ps1 -ProcessName WINWORD -ReturnCount 1

# List top 5 iexplore processes With highest CPU utilization, show result in a gridview:
.\PSGetTop.ps1 -ProcessName iexplore -ReturnCount 5 -GridView

# To kill a process with Process Id 1111, you can type:
(Get-Process -Id 1111).Kill()

# To get a list of all uniqe programs that run processes, try this:
Get-Process | Group-Object Name | select Count,Name | ft -AutoSize

Script PSGetTop.ps1:
Param([string]$ProcessName, [int]$SelectFirst, [switch]$GridView)

If (! $ProcessName) { $ProcessName = '*' }
If (! $SelectFirst) { $SelectFirst = 5 }

If ($ProcessName -eq '*') {
  $ProcessList = gwmi Win32_PerfFormattedData_PerfProc_Process | select IDProcess,Name,PercentProcessorTime | where { $_.Name -ne "_Total" -and $_.Name -ne "Idle"} | sort PercentProcessorTime -Descending | select -First $SelectFirst
Else {
  $ProcessList = gwmi Win32_PerfFormattedData_PerfProc_Process | where {$_.Name -eq $ProcessName} | select IDProcess,Name,PercentProcessorTime | sort PercentProcessorTime -Descending | select -First $SelectFirst
$TopProcess = @()
ForEach ($Process in $ProcessList) {
  $row = new-object PSObject -Property @{
    Id = $Process.IDProcess
    Name = $Process.Name
    User = (gwmi Win32_Process | where {$_.ProcessId -eq $Process.IDProcess}).GetOwner().User
    CPU = $Process.PercentProcessorTime
    Description = (Get-Process -Id $Process.IDProcess).Description
  $TopProcess += $row

If ($GridView) {
  $TopProcess | sort CPU -Descending | select Id,Name,User,CPU,Description | Out-GridView
Else {
  $TopProcess | sort CPU -Descending | select Id,Name,User,CPU,Description | ft -AutoSize