What's Running: `Get-Process` and `Stop-Process`
Every running program is a process with a number, its Id: Get-Process lists them with their memory (WS) and processor time (CPU), Sort-Object puts the busiest first, CommandLine tells two PowerShells apart, and Stop-Process -Id stops one, after a rehearsal with -WhatIf.
Apprentice · PowerShell · Operating System · Updated
After this lesson you can
- List running programs with Get-Process, sort them by memory or CPU, and read a row's WS(M), CPU(s), Id and ProcessName
- Find a runaway process by its Id or its command line, and stop only it with Stop-Process -Id, rehearsing with -WhatIf first
Key takeaways
- A process is a program while it runs. Each one gets a number, its Id, and Get-Process lists them: one row each, with its memory (WS) and processor time (CPU).
- Sort-Object WS -Descending or CPU -Descending puts the programs using the most first. CPU(s) is seconds of work since it started, so a runaway's number climbs fast.
- Every PowerShell window is a process named pwsh. Its CommandLine, the command that started it, tells them apart, and $PID is the Id of the window you're typing in.
- Stop-Process -Id stops one process at once, with no chance to save. Rehearse with -WhatIf first, and try Ctrl+C or closing its window before you force it.
- Stop-Process -Name stops every process with that name, so use it only when the name belongs to that one program alone.
Your laptop was fine an hour ago. Now the fan is roaring and every click takes a second to answer. Something is working the computer hard, and you want to know what. Most people open Task Manager, and that's a fine door in. PowerShell answers the same question with Get-Process, and then it can do things Task Manager can't: save the list, check it from a script every morning, or stop the same stuck program on ten laptops at once. An IT help-desk tech asks "what's running?" a dozen times a day.
This module is about looking after Windows, so it's for Windows only. Get-Process and Stop-Process also work in PowerShell on a Mac or Linux; most of the module's other commands don't.
Every running program is a process
A recipe in a cookbook doesn't cook anything; a cook following it does. Programs work the same way. The file on the disk is the recipe, and each time it runs, Windows starts a process: the program at work. Like tickets at a deli counter, each process gets a number, its process ID, or Id.
Get-Process lists them. With -Name, it lists only the processes with that name. Here's File Explorer, which also draws the taskbar:
Get-Process -Name explorer
NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName
------ ----- ----- ------ -- -- -----------
224 2,542.89 430.13 5,885.11 7404 1 explorer
113 204.46 208.85 6,155.39 61600 1 explorer
106 174.89 190.01 342.09 87772 1 explorer
Three explorer processes on this computer, each with its own Id. The columns that matter most:
- WS(M): the memory it's using right now, in megabytes (MB). WS is short for working set.
- CPU(s): how many seconds of work the processor has done for it since it started. It's a running total, not how busy it is this moment.
- Id: its process ID. Commands that stop or watch one process name it by this number.
- ProcessName: the program's name, without
.exe.
NPM and PM are other kinds of memory, and SI is the sign-in session it belongs to; you can leave them for now. Your numbers will be different: Ids are handed out as programs start.
Who's using the most? Sort it
Each row is an object, so Sort-Object (Sorting: Sort-Object) can put the biggest first. svchost is the Windows program that runs its background services (Services: Get-Service and Restart-Service comes back to it). Here are its three processes using the most memory:
Get-Process -Name svchost | Sort-Object WS -Descending | Select-Object -First 3
NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName
------ ----- ----- ------ -- -- -----------
26 110.16 101.41 0.00 7676 0 svchost
18 32.44 81.80 0.00 6208 0 svchost
40 2,060.21 80.82 176.23 3312 1 svchost
WS sorts by memory and CPU by processor time. The 0.00 rows aren't idle: Windows keeps the CPU time of its own system processes from a window that isn't running as administrator.
Try it. Get-Process | Sort-Object WS -Descending | Select-Object -First 5 lists the five programs on your PC using the most memory right now. Change WS to CPU for the five that have worked the hardest since they started.
Find the runaway
Make a practice program that misbehaves on purpose. runaway.ps1 says its own Id ($PID, read "the value of PID"), then counts as fast as it can, forever:
New-Item -ItemType Directory -Force -Path "$HOME\terminal-practice\processes" | Out-Null
Set-Location "$HOME\terminal-practice\processes"
Set-Content -Path runaway.ps1 -Value '# runaway.ps1: stuck in a loop, counting as fast as it can, forever.', 'Write-Output "Runaway started as process $PID. Press Ctrl+C to stop it."', '$n = 0', 'while ($true) { $n++ }'
Open a second tab in Windows Terminal (Ctrl+Shift+T), and start the runaway there, as its own PowerShell (Run It from Anywhere showed -NoProfile and -File):
Set-Location "$HOME\terminal-practice\processes"
pwsh -NoProfile -File .\runaway.ps1
Runaway started as process 83740. Press Ctrl+C to stop it.
Back in the first tab, look for it. Every PowerShell window is a process named pwsh, so Get-Process -Name pwsh lists yours too. Each process's CommandLine, the command that started it, tells them apart:
Get-Process -Name pwsh | Where-Object CommandLine -like '*runaway*'
NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName
------ ----- ----- ------ -- -- -----------
55 41.80 95.66 12.11 83740 1 pwsh
Wait five seconds and ask again, by its Id this time:
Get-Process -Id 83740
NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName
------ ----- ----- ------ -- -- -----------
54 40.16 92.95 25.09 83740 1 pwsh
CPU(s) jumped from 12 to 25 in a few seconds: it's working flat out, every moment. That climb, not the size of the number, is what gives a runaway away. Your number won't be 83740. The window you're typing in has an Id too, in $PID. That's the one never to stop:
$PID
106780
Stop it, politely first
Stopping a program from outside is pulling its plug: it gets no chance to save anything. So try the polite ways first. A program running in a terminal stops when you press Ctrl+C in its own window, and a program with a window closes the usual way, asking to save if it needs to. When it won't, rehearse first, the way Deleting Safely: Remove-Item, -WhatIf and -Confirm taught:
Stop-Process -Id 83740 -WhatIf
What if: Performing the operation "Stop-Process" on target "pwsh (83740)".
The name in brackets is the right one, so do it for real. Stop-Process prints nothing when it works; asking for the Id again proves it's gone:
Stop-Process -Id 83740
Get-Process -Id 83740
Get-Process: Cannot find a process with the process identifier 83740.
In the second tab, the prompt is back: only the runaway's PowerShell stopped.
Stop-Process -Name stops every process with that name. Stop-Process -Name pwsh would close every PowerShell window you have, this one included. Use -Name only when the name belongs to that one program alone, and add -Confirm to be asked about each one. A window that isn't running as administrator can stop only the programs running under your own account; that's a safety rail, not a fault.
The mouse's door is Task Manager (Ctrl+Shift+Esc). Its Processes page sorts by CPU or Memory, its Details page shows each process's Id in the PID column, and End task does what Stop-Process does.
Try it in the terminal
Terminal Quest: Mission Control, goal 2: played right on the lesson page.
An alarm at Mission Control won't stop beeping. Find it with Get-Process, then stop it. In the game it has a name of its own, alarm, so -Name is safe there.
Check yourself
2 questions to try on the lesson page.
So what
When a computer slows down, Get-Process sorted by memory or CPU names the culprit in seconds, and its Id lets you stop that one program and nothing else.