cheat sheet
tasklist
Display all running processes on a local or remote Windows machine with PID, memory usage, session, and optional service or module details — the cmd.exe equivalent of Task Manager for scripts.
tasklist — List Running Processes
What it is
tasklist is a built-in Windows command that enumerates all running processes and reports their image name, PID, session name, session number, and memory usage. It can optionally list the services hosted by a process (/svc), the DLLs loaded by a process (/m), and supports filter expressions to narrow the output. Use tasklist when you need a scriptable process snapshot — particularly in combination with taskkill to find and terminate specific processes. The PowerShell equivalent is Get-Process.
Availability
tasklist ships as C:\Windows\System32\tasklist.exe on Windows XP and later.
tasklist /?
Output:
TASKLIST [/S system [/U username [/P [password]]]]
[/M [module] | /SVC | /V] [/FI filter] [/FO format] [/NH]
Syntax
tasklist [/S host] [/U user] [/P pass] [/M [module]] [/SVC] [/V] [/FI filter] [/FO TABLE|LIST|CSV] [/NH]
Output: (process list)
Essential options
| Switch | Meaning |
|---|---|
/FO TABLE | Tabular output (default) |
/FO LIST | One field per line |
/FO CSV | Comma-separated values — best for scripting |
/NH | Suppress column headers |
/V | Verbose: add window title, CPU time, user name |
/M [module] | List DLLs loaded by each process (optionally filter by module name) |
/SVC | Show services hosted in each process |
/FI filter | Apply a filter expression (see filter section below) |
/S host | Query a remote machine |
/U domain\user | Credentials for remote query |
/P password | Password for /U |
Basic process list
Running tasklist without arguments produces a table of every process with PID, session, and memory usage.
tasklist
Output:
Image Name PID Session Name Session# Mem Usage
========================= ======== ================ =========== ============
System Idle Process 0 Services 0 8 K
System 4 Services 0 1,440 K
Registry 100 Services 0 42,440 K
smss.exe 412 Services 0 992 K
csrss.exe 680 Services 0 5,124 K
...
notepad.exe 8420 Console 1 23,456 K
CSV format for scripting
/FO CSV outputs a header row followed by one data row per process, suitable for parsing with for /f or importing into Excel or a SIEM.
tasklist /fo csv
Output:
"Image Name","PID","Session Name","Session#","Mem Usage"
"System Idle Process","0","Services","0","8 K"
"System","4","Services","0","1,440 K"
...
"notepad.exe","8420","Console","1","23,456 K"
tasklist /fo csv /nh
Output:
"System Idle Process","0","Services","0","8 K"
"System","4","Services","0","1,440 K"
...
Filtering with /FI
/FI applies a filter using fieldname operator value syntax. Multiple /FI flags are ANDed together. Supported operators: eq, ne, gt, lt, ge, le.
| Filter field | Type | Example |
|---|---|---|
IMAGENAME | string | /FI "IMAGENAME eq notepad.exe" |
PID | numeric | /FI "PID eq 8420" |
SESSION | numeric | /FI "SESSION eq 1" |
SESSIONNAME | string | /FI "SESSIONNAME eq Console" |
STATUS | string | /FI "STATUS eq Not Responding" |
MEMUSAGE | numeric (KB) | /FI "MEMUSAGE gt 100000" |
USERNAME | string | /FI "USERNAME eq alicedev" |
SERVICES | string | /FI "SERVICES eq wuauserv" |
WINDOWTITLE | string | /FI "WINDOWTITLE eq Untitled*" |
MODULES | string | /FI "MODULES eq ntdll.dll" |
CPUTIME | string (HH:MM:SS) | /FI "CPUTIME gt 00:10:00" |
tasklist /fi "IMAGENAME eq notepad.exe"
Output:
Image Name PID Session Name Session# Mem Usage
========================= ======== ================ =========== ============
notepad.exe 8420 Console 1 23,456 K
rem All processes using more than 100 MB
tasklist /fi "MEMUSAGE gt 102400"
Output:
Image Name PID Session Name Session# Mem Usage
========================= ======== ================ =========== ============
chrome.exe 6124 Console 1 512,340 K
explorer.exe 3456 Console 1 145,232 K
rem Find non-responding processes
tasklist /fi "STATUS eq Not Responding"
Output:
Image Name PID Session Name Session# Mem Usage
========================= ======== ================ =========== ============
myapp.exe 7890 Console 1 234,567 K
Services per process (/SVC)
/SVC adds a Services column listing every Windows service hosted within each svchost.exe instance — essential for identifying which service group owns a given svchost PID.
tasklist /svc
Output:
Image Name PID Services
========================= ======== ============================================
System Idle Process 0 N/A
System 4 N/A
svchost.exe 960 DcomLaunch, PlugPlay, Power
svchost.exe 1256 RpcEptMapper, RpcSs
svchost.exe 1488 BrokerInfrastructure, DPS, ...
...
notepad.exe 8420 N/A
rem Find the svchost hosting the Windows Update service
tasklist /svc | findstr "wuauserv"
Output:
svchost.exe 2340 wuauserv
Loaded modules (/M)
/M lists every DLL loaded by each process. Optionally provide a DLL name fragment to filter to only processes loading that module.
tasklist /m ntdll.dll
Output:
Image Name PID Modules
========================= ======== ============
System Idle Process 0 N/A
smss.exe 412 ntdll.dll
csrss.exe 680 ntdll.dll
...
Verbose output (/V)
/V adds window title, CPU time, and the user account owning each process — the closest equivalent to Task Manager's Details view.
tasklist /v /fi "IMAGENAME eq notepad.exe"
Output:
Image Name PID Session Name Ses# Mem Usage Status User Name CPU Time Window Title
============= ===== ============= ===== ========= ========= =========== ========== ===============
notepad.exe 8420 Console 1 23,456 K Running myhost\alicedev 0:00:00 Untitled - Notepad
Remote process list (/S)
/S queries a remote machine. Requires network access and the Remote Registry service running on the target.
tasklist /s myhost /u DOMAIN\alicedev
Output:
Password: (prompted)
Image Name PID Session Name Session# Mem Usage
...
Common pitfalls
- No wildcard in
/FI IMAGENAME—IMAGENAME eq note*does not work; usefindstrto filter output instead:tasklist | findstr "note". - "INFO: No tasks are running…" — the filter matched nothing; this is not an error but has exit code 0; check
errorlevelis unreliable for detecting missing processes. /Mwithout a module name lists all DLLs — output can be very large; always filter with a module name or pipe tofindstr.- Remote
/Sneeds Remote Registry service — the service must be running on the target machine; it is disabled by default on modern Windows. /Vadds CPU time, not CPU % — for live CPU percentage, use PowerShellGet-Processor Task Manager.
Real-world recipes
Check whether a process is running in a script
@echo off
tasklist /fi "IMAGENAME eq myapp.exe" 2>NUL | findstr "myapp.exe" >NUL
if errorlevel 1 (
echo myapp.exe is not running
) else (
echo myapp.exe is running
)
Output:
myapp.exe is not running
Get PID of a named process for use with taskkill
for /f "tokens=2" %p in ('tasklist /fi "IMAGENAME eq notepad.exe" /fo csv /nh') do (
echo Notepad PID: %~p
)
Output:
Notepad PID: 8420
Export full process snapshot for a support ticket
tasklist /v /fo csv > %TEMP%\procs_%COMPUTERNAME%.csv
echo Saved to %TEMP%\procs_%COMPUTERNAME%.csv
Output:
Saved to C:\Users\alicedev\AppData\Local\Temp\procs_MYHOST.csv
Find all svchost PIDs and their services
tasklist /svc /fi "IMAGENAME eq svchost.exe" /fo list
Output:
Image Name: svchost.exe
PID: 960
Services: DcomLaunch, PlugPlay, Power
Image Name: svchost.exe
PID: 1256
Services: RpcEptMapper, RpcSs
...
Filter operators in depth
The /FI filter language uses three-token expressions of the form FIELD OP VALUE. The operator set is small but the field-to-operator mapping is strict — numeric operators on string fields, or vice versa, produce "Invalid argument/option" with exit code 1 rather than empty output. Knowing which operators are legal per field saves a lot of script debugging.
rem Operators by field type
rem - String fields: eq, ne (no greater-than/less-than)
rem - Numeric fields: eq, ne, gt, lt, ge, le
rem - Status field: eq, ne against "Running" | "Not Responding" | "Unknown"
Output: (none — comments only, reference for the table below)
rem Multiple /FI flags are ANDed; there is no OR within tasklist itself
tasklist /fi "USERNAME eq myhost\alicedev" /fi "MEMUSAGE gt 100000" /fi "STATUS eq Running"
Output:
Image Name PID Session Name Session# Mem Usage
========================= ======== ================ =========== ============
chrome.exe 6124 Console 1 512,340 K
code.exe 8732 Console 1 287,116 K
For OR-logic, run two tasklist invocations and merge the output:
( tasklist /fi "IMAGENAME eq chrome.exe" /fo csv /nh ^
& tasklist /fi "IMAGENAME eq msedge.exe" /fo csv /nh ) > browsers.csv
Output: (no console output — browsers.csv contains both result sets)
PowerShell equivalents
PowerShell's Get-Process (alias gps/ps) is the modern replacement for tasklist. It returns rich System.Diagnostics.Process objects instead of fixed-width text, so filtering and aggregation use the pipeline rather than a custom mini-language. Reach for it whenever you need CPU%, parent PID, start time, or anything else tasklist cannot show.
Basic listing
Get-Process
Output:
NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName
------ ----- ----- ------ -- -- -----------
11 2.41 8.31 0.06 8420 1 notepad
45 96.15 145.22 124.50 6124 1 chrome
Filtering with the pipeline
Get-Process | Where-Object { $_.WorkingSet64 -gt 100MB } |
Sort-Object WorkingSet64 -Descending |
Select-Object -First 10 Name, Id, @{N='WS(MB)';E={[int]($_.WorkingSet64/1MB)}}
Output:
Name Id WS(MB)
---- -- ------
chrome 6124 512
explorer 3456 145
code 8732 287
Properties tasklist cannot show
Get-Process notepad | Select-Object Id, ProcessName, StartTime, Path,
@{N='CPU%';E={(Get-Counter "\Process($($_.Name))\% Processor Time").CounterSamples.CookedValue}}
Output:
Id : 8420
ProcessName : notepad
StartTime : 5/24/2026 9:14:22 AM
Path : C:\Windows\System32\notepad.exe
CPU% : 0.12
Parent PID, command line, and ownership via CIM
Get-Process does not expose the command line or parent PID directly. Use Get-CimInstance Win32_Process for those — it's also the documented replacement for the now-deprecated Get-WmiObject cmdlet.
Get-CimInstance Win32_Process -Filter "Name='notepad.exe'" |
Select-Object ProcessId, ParentProcessId, CommandLine,
@{N='Owner';E={ (Invoke-CimMethod $_ -MethodName GetOwner).User }}
Output:
ProcessId : 8420
ParentProcessId : 3456
CommandLine : "C:\Windows\System32\notepad.exe" C:\temp\notes.txt
Owner : alicedev
Get-WmiObjectis deprecated in PowerShell 7+ and removed from PowerShell Core entirely. New scripts targeting cross-version PowerShell should always useGet-CimInstanceandInvoke-CimMethod— they speak WS-MAN over WinRM remotely and are noticeably faster for local queries too.
Sysinternals PsList for richer detail
The Sysinternals pslist tool (see Sysinternals) is a drop-in upgrade when tasklist is too limited. It can show per-process CPU% sampled over an interval, full thread enumeration, memory categories (private bytes vs working set vs virtual), and per-process uptime. Unlike Get-Process, it stays purely command-line — no PowerShell required.
rem One-shot snapshot — like tasklist but with CPU and elapsed time
pslist -accepteula notepad
Output:
Name Pid Pri Thd Hnd Priv CPU Time Elapsed Time
notepad 8420 8 4 287 5,432 0:00:00.046 0:14:22.812
rem Sample CPU usage for 5 seconds — gives a real % instead of cumulative time
pslist -s 5 -accepteula
Output:
Name Pid CPU Time
chrome 6124 12.4% 2:15:33
code 8732 3.1% 0:42:18
explorer 3456 0.2% 1:14:55
The Sysinternals deep-dive covers the full toolkit including handle, procmon, and listdlls for when even pslist isn't enough.
Comparison: tasklist vs Get-Process vs wmic vs pslist
Pick a tool by the question being asked. All four are scriptable; they differ in machine-readability, available properties, and platform survival.
| Capability | tasklist | Get-Process | Get-CimInstance Win32_Process | pslist |
|---|---|---|---|---|
| Built-in | yes | yes (PowerShell) | yes (PowerShell) | no — Sysinternals |
| CPU percent | no | indirect | no | yes |
| Command line | no | no | yes | no |
| Parent PID | no | no (ParentId in PS7+) | yes | yes |
| Process owner | with /V only | no | via GetOwner() method | no |
| Loaded modules | yes (/m) | yes (.Modules) | no | no (use listdlls) |
| Services hosted | yes (/svc) | no | indirect | no |
| Remote machine | yes (/S) | yes (-ComputerName) | yes (-ComputerName) | yes (\\host) |
| Survives 2025+ Windows | yes | yes | yes | yes |
| Object pipeline | no — fixed text | yes | yes | no |
A useful heuristic: use tasklist for batch scripts and quick checks, Get-Process for any logic that needs to compose with other PowerShell, Get-CimInstance Win32_Process when you specifically need command line or parent PID, and pslist when you need CPU% from a non-PowerShell shell.
Exit codes and detecting "no match"
tasklist returns 0 in nearly every scenario — including the "no match found" case, which prints to stderr but does not raise an error level. Scripts must scan the output rather than trust %ERRORLEVEL%.
tasklist /fi "IMAGENAME eq notarealprocess.exe"
echo Exit code: %ERRORLEVEL%
Output:
INFO: No tasks are running which match the specified criteria.
Exit code: 0
The canonical "is it running?" check uses findstr as the actual predicate:
tasklist /fi "IMAGENAME eq myapp.exe" 2>nul | findstr /I /C:"myapp.exe" >nul
if errorlevel 1 (
echo NOT running
) else (
echo running
)
Output:
NOT running
PowerShell's equivalent is cleaner because it returns $null rather than printing:
if (Get-Process myapp -ErrorAction SilentlyContinue) {
Write-Host "running"
} else {
Write-Host "NOT running"
}
Output:
NOT running
Memory units and accuracy
Mem Usage in tasklist is the working set in KB — the resident set, comparable to RSS on Linux. It does not include paged-out memory, kernel-paged pool, or commit charge. For accurate memory analysis prefer one of the following.
| Metric | What it means | Where to get it |
|---|---|---|
Working Set (Mem Usage) | Resident pages in RAM right now | tasklist, Get-Process.WorkingSet64 |
| Private Bytes | Pages backed only by paging file (a process's "real" footprint) | Get-Process.PrivateMemorySize64, pslist |
| Commit Size | Memory the process has reserved (committed) | Get-CimInstance Win32_Process.VirtualSize |
| Virtual Size | Total address space — includes shared images | Same as above |
| Pagefile Usage | Bytes paged out | Get-CimInstance.PageFileUsage |
Get-Process chrome |
Select-Object Id,
@{N='WS(MB)';E={[int]($_.WorkingSet64/1MB)}},
@{N='Private(MB)';E={[int]($_.PrivateMemorySize64/1MB)}},
@{N='VM(MB)';E={[int]($_.VirtualMemorySize64/1MB)}}
Output:
Id WS(MB) Private(MB) VM(MB)
-- ------ ----------- ------
6124 512 478 2104
6130 214 189 980
Performance and remote queries
tasklist is fast on a local machine (~30–80 ms cold, mostly spent walking the process list once). Remote queries via /S are an order of magnitude slower because the call traverses the Remote Registry service over RPC.
| Mode | Typical wall time on a healthy fleet box |
|---|---|
Local tasklist | 30–80 ms |
Local tasklist /v /svc | 200–500 ms (enumerates services + window titles) |
Remote tasklist /s host | 1.5–5 s (RPC handshake dominates) |
Get-Process -ComputerName host | 1–3 s (WMI/CIM, slightly faster than /S) |
Get-Process over Invoke-Command -Session $s | ~200 ms after first call (WinRM session reuse) |
For repeated remote polls in a monitoring loop, open a persistent WinRM session and reuse it rather than spawning tasklist /S every iteration:
$s = New-PSSession -ComputerName myhost
Invoke-Command -Session $s -ScriptBlock {
Get-Process | Where-Object WorkingSet64 -gt 200MB
}
Remove-PSSession $s
Output:
NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName PSComputerName
------ ----- ----- ------ -- -- ----------- --------------
45 96.15 512.40 1240.10 6124 1 chrome myhost
38 78.50 287.11 412.30 8732 1 code myhost
Cross-platform comparison: tasklist vs ps/htop
Coming from Linux, the closest analogues are ps, pgrep, and htop (see the htop deep-dive). The semantics diverge in two important ways: Windows process trees flatten more aggressively (orphans reparent to PID 4 System), and Windows distinguishes session IDs (TS sessions, not just controlling terminals).
| Linux | Windows equivalent |
|---|---|
ps aux | tasklist /v |
ps -ef --forest | tasklist /v /svc (no built-in tree; use pslist -t) |
pgrep -f "notepad" | tasklist /fi "IMAGENAME eq notepad.exe" |
ps -o pid,comm,%cpu,%mem | `Get-Process |
top / htop | `Get-Process |
pidof myapp | for /f "tokens=2" %P in ('tasklist /fi "imagename eq myapp.exe" /fo csv /nh') do @echo %P |
ps --ppid 1234 | Get-CimInstance Win32_Process -Filter "ParentProcessId=1234" |
lsof -p 1234 | handle -p 1234 (Sysinternals) |
tasklistdoes not show a process tree. For a visual hierarchy from the command line, usepslist -t -accepteula(Sysinternals) — it indents children under their parents the same waypstreedoes on Linux.
Real-world deep recipes
Top-10 memory consumers as a one-liner
tasklist /fo csv /nh > %TEMP%\plist.csv
powershell -NoProfile -Command ^
"Import-Csv %TEMP%\plist.csv -Header 'Image','PID','Sess','S#','Mem' | ^
ForEach-Object { $_.Mem = [int]($_.Mem -replace '[^0-9]','') ; $_ } | ^
Sort-Object Mem -Descending | Select-Object -First 10 | Format-Table"
Output:
Image PID Sess S# Mem
----- --- ---- -- ---
chrome.exe 6124 Console 1 512340
code.exe 8732 Console 1 287116
explorer.exe 3456 Console 1 145232
...
Wait for a process to exit then run a follow-up
@echo off
:wait_loop
tasklist /fi "IMAGENAME eq longjob.exe" 2>nul | findstr /I /C:"longjob.exe" >nul
if not errorlevel 1 (
timeout /t 5 /nobreak >nul
goto wait_loop
)
echo longjob.exe finished; running follow-up...
call post_job.bat
Output:
longjob.exe finished; running follow-up...
Audit all processes loading a suspect DLL
When IT/security wants to find every process loading bad.dll across an audit run, tasklist /m is the simplest discovery tool. Pipe through findstr to drop "N/A" rows and keep only matches:
tasklist /m bad.dll 2>nul | findstr /V "N/A" | findstr /V "^Image Name" | findstr /V "^="
Output:
suspectapp.exe 7890 bad.dll
otherapp.exe 12044 bad.dll
Snapshot to JSON for ingest by an observability pipeline
tasklist itself cannot emit JSON. Pipe through PowerShell to convert:
tasklist /v /fo csv > %TEMP%\snap.csv
powershell -NoProfile -Command ^
"Import-Csv %TEMP%\snap.csv | ConvertTo-Json -Depth 3" > %TEMP%\snap.json
Output: (none — written to %TEMP%\snap.json)
[
{ "Image Name": "notepad.exe", "PID": "8420", "Session Name": "Console",
"Session#": "1", "Mem Usage": "23,456 K", "Status": "Running",
"User Name": "myhost\\alicedev", "CPU Time": "0:00:00", "Window Title": "Untitled - Notepad" }
]
Compare two snapshots to find new processes
$before = tasklist /fo csv | ConvertFrom-Csv
Start-Sleep 30
$after = tasklist /fo csv | ConvertFrom-Csv
Compare-Object $before $after -Property PID -PassThru |
Where-Object SideIndicator -eq '=>' |
Select-Object PID, 'Image Name', 'Mem Usage'
Output:
PID Image Name Mem Usage
--- ---------- ---------
14228 msedge.exe 212,500 K
14290 msedgewebview2.exe 88,310 K
Security and forensics notes
tasklist itself is unprivileged — any user can list processes they have query access to. Several caveats matter for IR and audit work:
- Protected processes (
csrss.exe, antivirus engines, LSASS on modern Windows) refuse to expose their command line or modules to non-SYSTEMcallers;tasklist /msimply omits them with no warning. - Hidden processes via rootkit are invisible to
tasklistbecause it relies on the documentedToolhelp32/NtQuerySystemInformationpaths the rootkit will have hooked. For forensic snapshots use a kernel-level tool — Sysinternalspslistqueries the same APIs butprocmonandhandlereach into the kernel handle tables. - Username field can be spoofed in older Windows by token impersonation; cross-check with
Get-CimInstance Win32_Processand(Invoke-CimMethod -MethodName GetOwner)for the authoritative owner SID. - Remote
/Swithout explicit/Uuses the current credentials — easy to leak admin credentials onto a compromised host. In hardened environments use a dedicated audit account.
See also
- taskkill — Terminate Processes — pair
tasklistwithtaskkillfor find-and-kill scripts. - sc — Service Control Manager CLI — when the PID belongs to
svchost.exe,scis the next step. - wmic — Windows Management Instrumentation CLI — legacy but still useful for command-line and parent PID until you migrate to CIM.
- Sysinternals — PsExec, Handle, ProcMon and the Sysadmin Toolkit —
pslist,handle,procmon,listdllsfor deeper process spelunking. - htop — Interactive process viewer — the Linux counterpart for live process inspection.
- ps and netstat — cross-platform mental model for process listings.
Sources
learn.microsoft.com — tasklist · learn.microsoft.com — Get-Process · learn.microsoft.com — Get-CimInstance