PowerShell Get-Process Remote Computer: Manage Remote Processes

PowerShell Get-Process Remote Computer: Manage Remote Processes

PowerShell Tips Editor 3 min read
PowerShell Get-Process Remote Computer: Manage Remote Processes

A runaway process is consuming all CPU on a remote server, the application team is paging you, and opening an RDP session will take three minutes you do not have. With PowerShell get process remote computer techniques, you can identify and kill the offending process in under 30 seconds from your own workstation. This post covers querying remote processes with Invoke-Command, killing processes remotely, checking for a process by name, using CIM sessions for persistent queries, and bulk process checks across a server list.

Get Remote Process with -ComputerName

Get-Process accepts a -ComputerName parameter in Windows PowerShell 5.1, but this parameter is deprecated and removed in PowerShell 7. For cross-version compatibility, use Invoke-Command instead (shown in the next section). On PS 5.1 environments where it still works:

# Windows PowerShell 5.1 only — deprecated parameter
Get-Process -ComputerName "Server01" | Sort-Object CPU -Descending | Select-Object -First 10 Name, CPU, WorkingSet

Using Invoke-Command for Remote Process

Invoke-Command is the correct, cross-version approach. It runs the Get-Process call inside a PowerShell remoting session on the target computer, then returns the results as deserialized objects in your local session:

$topProcs = Invoke-Command -ComputerName "Server01" -ScriptBlock {
    Get-Process |
        Sort-Object CPU -Descending |
        Select-Object -First 10 Name, Id, CPU,
            @{N='MemoryMB'; E={[Math]::Round($_.WorkingSet64 / 1MB, 1)}}
}
$topProcs | Format-Table -AutoSize
Name        Id      CPU   MemoryMB
----        --      ---   --------
sqlservr  1248  4821.3     2048.0
w3wp      3304   312.7      512.3
svchost    892    18.2       64.1

Kill a Remote Process

To stop a process on a remote machine, pass the process ID or name to Stop-Process inside Invoke-Command. Always confirm the process name first to avoid accidentally stopping the wrong process:

Invoke-Command -ComputerName "Server01" -ScriptBlock {
    param($ProcessName)
    $proc = Get-Process -Name $ProcessName -ErrorAction SilentlyContinue
    if ($proc) {
        $proc | Stop-Process -Force
        Write-Host "Stopped $($proc.Count) instance(s) of '$ProcessName'"
    } else {
        Write-Host "Process '$ProcessName' not found on $env:COMPUTERNAME"
    }
} -ArgumentList "w3wp"

Check Process Exists on Remote Host

Before taking any action, verify a process is running. Return a simple $true/$false from the remote session:

function Test-RemoteProcess {
    param(
        [string]$ComputerName,
        [string]$ProcessName
    )
    Invoke-Command -ComputerName $ComputerName -ScriptBlock {
        param($name)
        [bool](Get-Process -Name $name -ErrorAction SilentlyContinue)
    } -ArgumentList $ProcessName
}

if (Test-RemoteProcess -ComputerName "Server01" -ProcessName "notepad") {
    Write-Host "notepad is running on Server01"
}

CIM Session for Persistent Remote Queries

When you need to query multiple process-related properties repeatedly, a CimSession avoids the overhead of opening a new connection on every call. Use Get-CimInstance with Win32_Process for richer data than Get-Process provides:

$cs = New-CimSession -ComputerName "Server01"

# Get processes with owner information (not available in Get-Process)
$procs = Get-CimInstance -CimSession $cs -ClassName Win32_Process |
    Select-Object Name, ProcessId, WorkingSetSize,
        @{N='Owner'; E={ ($_ | Invoke-CimMethod -MethodName GetOwner).User }}

$procs | Sort-Object WorkingSetSize -Descending | Select-Object -First 5

Remove-CimSession $cs

Bulk Process Check Across Servers

Use Invoke-Command with an array of computer names and a -ThrottleLimit to query multiple servers in parallel:

$servers = Get-Content "C:\Scripts\servers.txt"

$results = Invoke-Command -ComputerName $servers -ThrottleLimit 20 -ScriptBlock {
    $cpu = Get-Process | Sort-Object CPU -Descending | Select-Object -First 1
    [PSCustomObject]@{
        Server     = $env:COMPUTERNAME
        TopProcess = $cpu.Name
        CPU        = [Math]::Round($cpu.CPU, 1)
        MemoryMB   = [Math]::Round($cpu.WorkingSet64 / 1MB, 1)
    }
} 2>&1 | Where-Object { $_ -isnot [System.Management.Automation.ErrorRecord] }

$results | Sort-Object CPU -Descending | Format-Table -AutoSize

Common Errors and Fixes

  • Get-Process -ComputerName deprecated in PS7 — use Invoke-Command. Scripts using Get-Process -ComputerName break silently or throw errors in PowerShell 7. Replace all such calls with Invoke-Command -ComputerName ... -ScriptBlock { Get-Process ... } for forward-compatible code.
  • Requires WinRM enabled on remote machine. Invoke-Command and CimSession over WS-Man both require WinRM to be running and reachable on the target. Verify with Test-WSMan -ComputerName Server01. If WinRM is unavailable, fall back to DCOM-based CIM sessions using New-CimSessionOption -Protocol Dcom.

Related Cmdlets / See Also

Wrapping Up

Remote process management in PowerShell centers on Invoke-Command for cross-version compatibility and CIM sessions for richer data. Check before you kill, pass process names via -ArgumentList to avoid scope issues, and use bulk Invoke-Command with -ThrottleLimit to query a hundred servers simultaneously.

Send-Item -To