cheat sheet

Sysinternals

Bootstrap and drive the headless Sysinternals utilities — PsExec, Handle, PsList, Autoruns, ProcMon, ListDLLs — for process spelunking, file-lock hunting, autostart auditing and scripted system tracing on Windows.

Sysinternals — PsExec, Handle, ProcMon and the Sysadmin Toolkit

What it is

The Sysinternals Suite is a collection of ~70 advanced Windows utilities originally written by Mark Russinovich and Bryce Cogswell at Sysinternals.com, now maintained by Microsoft. Where the in-box tasklist and taskkill answer only the most basic process questions, Sysinternals tools go several layers deeper: which file handle is locking a binary, which DLL is loaded by which process, what every autostart entry does at boot, and what a process actually touches on disk and registry from the moment it spawns. Reach for Sysinternals when the built-in CLI doesn't tell you enough — and reach for the headless variants (PsExec, Handle, PsList, autorunsc, ProcMon's /BackingFile, ListDLLs) when you need to script the answer rather than click through a GUI.

This page is a compendium covering the six tools most often used from the command line. All of them are EULA-gated on first launch; bypass the dialog non-interactively with -accepteula (or /accepteula for ProcMon).

What's new in 2026

Microsoft shipped a broad Sysinternals refresh on May 7, 2026 — keep your local copies current, several of the command-line tools picked up scriptable features:

ToolNew versionWhat changed
Autoruns / autorunsc.exev14.2First-class support for Windows packaged (MSIX/AppX) auto-start entries — the headless autorunsc -a * now surfaces Store apps that used to be invisible.
ProcDumpv12.0New -pt (process-tree) flag — dump the target and every descendant in one command, which closes the long-standing gap when triaging short-lived child processes.
Process Monitor (procmon.exe)v4.02Stability and filter-engine fixes; the /BackingFile switch remains the way to capture headlessly.
Process Explorerv17.12New event-monitoring details and bug fixes for Windows 11 26x builds.
DebugViewv5.01Reinstated Windows 10 support, added per-PID highlighting.
ZoomItv12.0Webcam overlay for video capture, video-trim append — relevant when recording demos from a console session.
NotMyFaultv4.5Refreshed driver signing for current Windows builds.
RAMMap / Sysmon / Coreinfov1.63 / v15.2 / v4.0Minor refreshes through Dec 2025 – May 2026.

Linux ports of the Sysinternals family (Sysmon for Linux, ProcMon for Linux, ProcDump for Linux, the new jcd directory navigator) now officially support RHEL 10, Debian 13, and Fedora 43. On Windows, all tools have first-class ARM64 builds — grab the SysinternalsSuite-ARM64.zip bundle for Snapdragon X devices instead of running x64 binaries under emulation.

Refresh your local toolkit:

powershell
# Re-download the full suite (x64)
Invoke-WebRequest https://download.sysinternals.com/files/SysinternalsSuite.zip -OutFile $env:TEMP\sys.zip
Expand-Archive $env:TEMP\sys.zip -DestinationPath "C:\Tools\Sysinternals" -Force

Install

The whole suite installs as a single zip from Microsoft or via either of the two major Windows package managers. WinGet is the most maintained channel; Chocolatey ships an equivalent metapackage.

cmd
rem WinGet (Windows 10 1809+ / 11) — installs to %ProgramFiles%\Sysinternals
winget install --id Microsoft.Sysinternals.Suite -e

rem Chocolatey — installs to C:\ProgramData\chocolatey\bin
choco install sysinternals -y

rem Scoop — extras bucket
scoop bucket add extras
scoop install sysinternals

rem Live network share (no install, always latest) — open in Explorer
start \\live.sysinternals.com\tools\

Output: (none — exits 0 on success)

The recommended PATH addition after install:

cmd
setx PATH "%PATH%;C:\ProgramData\chocolatey\lib\sysinternals\tools" /M

Output:

makefile
SUCCESS: Specified value was saved.

Choosing between the tools

The six headless tools below overlap on "what is this process doing" but each owns a specific axis. Pick by question:

QuestionToolWhy
Run a command on a remote machinepsexecLive remote interactive or silent exec
Which process has this file open?handleSearches handle tables system-wide
What handles does PID X own?handle -p PIDPer-process handle dump
Headless replacement for Task ManagerpslistPlain-text process snapshot with CPU/memory
What autostarts at boot/logon?autorunscEnumerates every autostart hook (~50 categories)
What files/registry does this process touch?procmon /BackingFileReal-time file + registry + network trace
Which DLLs are loaded by PID X?listdllsPer-process loaded-module list

Most Sysinternals CLI tools accept -accepteula so they never block on the first-run EULA dialog. Add it to every scripted invocation. ProcMon uses the /AcceptEula form (slash + camel-case).


PsExec — remote and elevated process execution

PsExec launches a process on a local or remote machine. Under the hood it copies a small service binary (psexesvc.exe) to the target's ADMIN$ share, registers and starts it, then proxies stdin/stdout back to the caller. Use it to run interactive shells in the NT AUTHORITY\SYSTEM context, to execute setup scripts across a fleet, or to grab a session in another user's logon — anything that requires "run this over there but pretend it's here".

Syntax

The base form is psexec [\\target] [options] command [args]. Without \\target, PsExec runs locally — the elevated/SYSTEM features still work.

cmd
psexec [\\computer[,...] | @file] [-u user [-p pass]] [-s|-e|-h|-i [n]] [-d] [-w dir] cmd [args]

Output: (none — exits 0 on success)

Essential options

SwitchMeaning
\\nameTarget computer (or \\host1,host2 or @hostlist.txt)
-u userUsername for the remote logon
-p passPassword (omit to prompt; passing on CLI exposes in process list)
-sRun as NT AUTHORITY\SYSTEM (local SYSTEM service)
-i [session]Interactive — show GUI on the target's console (-i 0 = console session)
-hRun elevated (use the High integrity token)
-eDon't load the user's profile (faster on remote, no %USERPROFILE%)
-dDon't wait — fire-and-forget
-w dirSet working directory on the target
-cCopy the program to the target first
-accepteulaSuppress the EULA dialog
-nobannerSuppress the copyright banner

Launch a local SYSTEM shell

The classic "look under the hood" move — opens a cmd.exe running as NT AUTHORITY\SYSTEM rather than your admin account. Useful for poking at services and registry keys protected from administrators.

cmd
psexec -s -i -accepteula cmd.exe

Output:

sql
PsExec v2.43 - Execute processes remotely
Copyright (C) 2001-2023 Mark Russinovich
Sysinternals - www.sysinternals.com

(new cmd window opens; running 'whoami' inside it prints:)
nt authority\system

Run a command on a remote machine

The most common everyday use — silent execution of a command on a server without RDP'ing in. The -h switch is important when the target has UAC enabled and you want the elevated token.

cmd
psexec \\myhost -u DOMAIN\alicedev -h -accepteula ipconfig /all

Output:

sql
PsExec v2.43 - Execute processes remotely
Copyright (C) 2001-2023 Mark Russinovich

(ipconfig output streamed back)
Windows IP Configuration
   Host Name . . . . . . . . . . . . : MYHOST
   Primary Dns Suffix  . . . . . . . : example.com
...

ipconfig exited on myhost with error code 0.

Run a command across many machines from a host list

PsExec accepts a @file of newline-separated hostnames and parallelises across them. Combine with -d to fire-and-forget for fast fan-out.

cmd
rem Roll out a hotfix script silently across the fleet
psexec @hosts.txt -u DOMAIN\alicedev -h -d -c -accepteula C:\scripts\hotfix.cmd

Output:

csharp
PsExec v2.43 - Execute processes remotely
...
Started hotfix.cmd on MYHOST with process ID 4521.
Started hotfix.cmd on FILESERVER with process ID 3320.
Started hotfix.cmd on WEB01 with process ID 7710.

Interactive remote GUI launch

-i 0 launches into the console session (session 0 on older Windows, the active user session on modern Windows when combined with -i <session>). Useful for kiosk troubleshooting where you want the GUI to actually appear on a user's screen.

cmd
psexec \\myhost -u DOMAIN\alicedev -i 1 -d -accepteula notepad.exe

Output:

csharp
notepad.exe started on myhost with process ID 5430.

Common PsExec pitfalls

  1. AV flags psexec.exe — Defender and most AV products quarantine the binary as a "hacktool" because of its abuse in pentests. Whitelist it explicitly for sysadmin workstations.
  2. ADMIN$ share required — the target machine must have ADMIN$ reachable; modern domain isolation policies sometimes block it. Test with dir \\target\ADMIN$.
  3. Password on CLI leaks-p hunter2 shows up in process listings on the source machine. Prefer omitting -p and being prompted, or use -u only and a saved Windows credential.
  4. PsExec leaves psexesvc.exe running on disconnect — if you Ctrl-C aggressively, the service may not get cleaned up. Remove with sc \\target stop psexesvc && sc \\target delete psexesvc.

Handle — find and dump open handles

handle.exe enumerates kernel handles — files, directories, registry keys, mutants, named pipes, sections, processes — and the processes that own them. Its killer feature is the "what has this file open?" query: when an installer says "the file is in use by another process", Handle tells you exactly which PID it is.

Syntax

handle [-a] [-l] [-u] [-c handle [-y]] [-s] [-p PID|name] [name]

cmd
handle [-a] [-p PID|name] [filename-fragment]

Output: (none — exits 0 on success)

Essential options

SwitchMeaning
-aAll handle types (default is files only)
-lList page-file backed sections (pagefile-backed memory)
-uShow username owning each handle
-cClose a specific handle (dangerous — see pitfall)
-sPrint a summary count per handle type
-pFilter by PID or process name
-accepteulaSuppress EULA

Find which process holds a file open

The bread-and-butter query. Pass any substring of the filename — Handle does a case-insensitive match across every file handle in the system.

cmd
handle -accepteula myapp.exe.config

Output:

arduino
Handle v5.0
Copyright (C) 1997-2022 Mark Russinovich

myapp.exe         pid: 7890  type: File        348: C:\Program Files\MyApp\myapp.exe.config
explorer.exe      pid: 3456  type: File        9D4: C:\Program Files\MyApp\myapp.exe.config

Per-process handle dump

-p narrows to a specific PID or process name. Combined with -a you get every handle that process owns, not just files.

cmd
handle -accepteula -p 7890 -a

Output:

yaml
myapp.exe pid: 7890 DOMAIN\alicedev
  18: File          C:\Program Files\MyApp\myapp.exe
  1C: File          C:\Windows\System32
  20: Key           HKLM\SOFTWARE\MyApp
  24: Mutant        \Sessions\1\BaseNamedObjects\MyAppSingleton
  28: Event         \Sessions\1\BaseNamedObjects\MyApp.Shutdown
  2C: File          C:\Users\alicedev\AppData\Local\MyApp\state.db

Summary counts

-s lists every handle type currently in use across the system with a count — a quick health check for handle leaks. A handle count climbing without bound is a classic memory-leak symptom.

cmd
handle -accepteula -s -p 7890

Output:

yaml
Handle type summary:
  ALPC Port       :  4
  Directory       :  3
  Event           : 76
  File            : 28
  IoCompletion    : 12
  Key             : 19
  Mutant          :  8
  Section         : 15
  Semaphore       :  4
  Thread          : 23
  Token           :  3
  WindowStation   :  1
  Total handles:   196

Common Handle pitfalls

  1. -c can crash applications — closing a handle the owning process still needs typically causes it to crash or hang. Use only as a last resort when restarting the process isn't possible.
  2. Output is a point-in-time snapshot — a process that opens and closes a file in a loop may not show up. Run repeatedly or use ProcMon for continuous tracing.
  3. Wildcards don't work — Handle does substring matching only; handle "*.log" matches the literal asterisk, not all log files. Just use handle .log.

PsList — text-mode Task Manager

pslist.exe is a fast, text-mode equivalent of Task Manager's Details tab. It's faster than tasklist /v and produces output that's easier to parse in scripts — fixed columns, no localisation surprises.

Syntax

cmd
pslist [-d] [-m] [-x] [-t] [-s [n]] [-r n] [\\computer] [name|PID]

Output: (none — exits 0 on success)

Essential options

SwitchMeaning
-dPer-thread detail (shows each thread state and CPU time)
-mMemory detail (working set, peak, virtual size, paged pool)
-xCombined — process + memory + thread
-tTree view (parent-child)
-s [n]Sample CPU usage every second for n seconds
-r nRefresh every n seconds (live monitor)
\\computerQuery a remote machine

Memory snapshot

The default columns are useful but -m gives the most actionable data for a memory-leak triage.

cmd
pslist -accepteula -m

Output:

yaml
PsList v1.4 - Process information lister
Copyright (C) 2000-2021 Mark Russinovich

Process memory detail for MYHOST:

Name                Pid      VM      WS    Priv Priv Pk   Faults   NonP Page
Idle                  0       0       8       0       0        0      0    0
System                4   14620    1440      40      48       43      0    0
smss                412    4448     992     328     376      385      4    4
csrss               680    9024    5124    1632    1768     2120      8    9
chrome             6124  234080  512340  189440  201230   480231     32   42
notepad            8420   65280   23456    8120    9540    18421      8    9

Process tree

-t indents children under parents — invaluable for spotting which process spawned a rogue child. Combine with -s 5 to also see a 5-second CPU sample.

cmd
pslist -accepteula -t

Output:

yaml
Process                              Pid Pri Thd  Hnd      VM      WS    Priv
Idle                                   0   0   8    0       0       8       0
  System                               4   8 195 4920   14620    1440      40
    smss                             412  11   2   53    4448     992     328
csrss                                680  13  11  595    9024    5124    1632
wininit                              720  13   1   88    9224    5640    1432
  services                           812   9  13  580   12880    7240    4320
    svchost                          960   8  19  680   24580   18420    9430
      RuntimeBroker                 4521   8  16  380   16240   13340    8420
    spoolsv                         2580   8  12  410   18880    8460    4920
explorer                            3456   8  82 2100  890000   65420   38420
  chrome                            6124   8  42 1850  234080  512340  189440
    chrome                          6130   8  18  580   80000   65280   42880

Autoruns CLI (autorunsc) — every autostart hook on the box

autorunsc.exe is the headless sibling of the famous Autoruns GUI. It enumerates every mechanism Windows uses to start something automatically — Run keys, Services, Scheduled Tasks, Winlogon, Print Monitors, Image File Execution Options, Boot Execute, AppInit DLLs, and dozens more. Used in incident response, malware triage, and "why is my laptop so slow at login" debugging.

Syntax

cmd
autorunsc [-a *|<categories>] [-c|-ct|-h|-m|-s|-t] [-u] [-f|-x] [-vt] [user]

Output: (none — exits 0 on success)

Essential options

SwitchMeaning
-a *All autostart categories (recommended — use -a then category letters to narrow)
-cCSV output
-ctTab-separated output
-hShow file hashes (MD5/SHA1/SHA256/IMP)
-sVerify digital signatures
-vQuery VirusTotal — -v rs to skip already-scanned files
-vtSubmit unknown files to VT (consent flag)
-uHide signed Microsoft entries (focus on third-party)
-fShow files-not-found entries (broken autostarts)
-xXML output
-mDon't show Microsoft entries (alias -u + signed-MS filter)
userTarget a specific user profile

A full system snapshot to CSV for triage

The recommended IR command: every category, hashes, signature verification, CSV output for diffing or pivoting in Excel.

cmd
autorunsc -accepteula -a * -c -h -s > C:\IR\autoruns_%COMPUTERNAME%_%DATE:~10,4%%DATE:~4,2%%DATE:~7,2%.csv

Output:

less
(nonefile written; CSV header is:)
Time,Entry Location,Entry,Enabled,Category,Profile,Description,Signer,Company,Image Path,Version,Launch String,MD5,SHA-1,PESHA-1,PESHA-256,SHA-256,IMP

Show only suspicious (third-party + unsigned) entries

Cut the signal-to-noise by hiding signed Microsoft entries. This is the first command in many malware triage runbooks.

cmd
autorunsc -accepteula -a * -m -s

Output:

arduino
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
  WeirdApp                           C:\Users\alicedev\AppData\Local\Temp\wapp.exe
    (Not verified)  Unknown Publisher
    File not signed
    Modified: 2026-05-22 02:18

Task Scheduler
  \Updater\Reflector
    (Not verified)
    C:\ProgramData\reflector\update.exe /quiet
    Modified: 2026-05-23 14:02

Compare snapshots over time

Save daily snapshots and diff them — any new line is something that just installed itself.

cmd
autorunsc -accepteula -a * -c -h -nobanner > today.csv
fc /n yesterday.csv today.csv

Output:

yaml
Comparing files YESTERDAY.CSV and TODAY.CSV
***** YESTERDAY.CSV
    312:  HKCU\...\Run,GoodApp,Enabled,Logon,...
***** TODAY.CSV
    312:  HKCU\...\Run,GoodApp,Enabled,Logon,...
    313:  HKCU\...\Run,WeirdApp,Enabled,Logon,...
*****

Autoruns category codes

When you don't need all 50 categories, narrow with letter codes:

CodeCategory
bBoot execute
dAppinit DLLs
eExplorer add-ons
gSidebar gadgets
hImage hijacks (IFEO)
iInternet Explorer add-ons
kKnown DLLs
lLogon entries (Run/RunOnce/RunOnceEx, Userinit, Shell)
mWMI providers
nWinsock providers
oCodecs
pPrinter monitor DLLs
rLSA providers
sServices
tScheduled tasks
wWinlogon entries
xSidebar gadgets
cmd
rem Just logon + services + scheduled tasks
autorunsc -accepteula -a lst -c -h

Output: (CSV with only those 3 categories)


ProcMon — scripted file/registry/network tracing

procmon.exe (Process Monitor) shows every file, registry, network, and process operation a system performs in real-time. Most people know it as a GUI; the CLI mode (/BackingFile, /AcceptEula, /Quiet, /Minimized, /Terminate) makes it scriptable for unattended capture — invaluable for catching what an installer or service does on a customer machine when you can't be there.

Syntax

ProcMon's CLI flags use /Slash rather than -dash, and there is no shortened headless binary — you drive the same procmon.exe (or procmon64.exe) that opens the GUI.

cmd
procmon /AcceptEula /Quiet /Minimized /BackingFile <pml> [/LoadConfig <pmc>] [/Runtime <sec>]
procmon /Terminate

Output: (none — exits 0 on success)

Essential options

SwitchMeaning
/AcceptEulaSuppress EULA dialog
/QuietDon't show splash screen
/MinimizedStart minimised
/BackingFile <pml>Write events to a .pml log file (must be specified for scripted capture)
/LoadConfig <pmc>Load a saved filter set
/Runtime <sec>Auto-stop after N seconds
/TerminateStop the currently running ProcMon instance
/PagingFile <pmb>Use a paging file for very large captures
`/SaveAs <csvxml>`
/OpenLog <pml>Open an existing capture (GUI mode)
/ProfilingEnable thread-profiling events

Capture 60 seconds of activity to a file

The minimal scripted capture — write a 60-second trace to a .pml log for later analysis in the ProcMon GUI on your own workstation.

cmd
procmon /AcceptEula /Quiet /Minimized /BackingFile C:\Traces\boot.pml /Runtime 60

Output: (none — file C:\Traces\boot.pml is created)

Capture until manually stopped

For longer captures, omit /Runtime and stop with /Terminate from a second prompt or after the repro step.

cmd
rem Terminal 1: start capture
procmon /AcceptEula /Quiet /Minimized /BackingFile C:\Traces\repro.pml

rem (run the repro on the same machine)

rem Terminal 2: stop the capture
procmon /Terminate

Output: (none — capture file written)

Boot logging (capture from system start)

/EnableBootLogging writes events that occurred before user logon — the earliest stages of boot. Re-run ProcMon after reboot with /Convert to materialise the boot log.

cmd
procmon /AcceptEula /EnableBootLogging
shutdown /r /t 0

rem After reboot, convert the boot log:
procmon /AcceptEula /ConvertBootLog C:\Traces\boot.pml

Output:

csharp
(none — file C:\Traces\boot.pml is created)

Convert a .pml to CSV for grep/scripting

ProcMon logs are a binary .pml format. For grep-friendly analysis, convert to CSV.

cmd
procmon /OpenLog C:\Traces\repro.pml /SaveAs C:\Traces\repro.csv

Output: (none — CSV file written)

Common ProcMon pitfalls

  1. Capture files balloon fast — on a busy server, a 60-second capture can be 500 MB+. Always set /BackingFile to a drive with space, and use saved filters (/LoadConfig) to prefilter at capture time.
  2. /Runtime not honoured if the kernel driver crashes — rare, but if you see no file produced, look at the System event log for PROCMON23 errors.
  3. GUI must be installed and run once interactively — first run of procmon.exe writes per-user settings; on a server you'll see nothing on subsequent silent runs. Pre-warm by RDP'ing in once and clicking "OK" on the EULA, then script with /AcceptEula afterwards.

ListDLLs — modules loaded by a process

listdlls.exe enumerates DLLs loaded into a process's address space — their name, base address, size, and digital-signature status. Use it to confirm an antivirus DLL is injected into your service, to spot a stale version of a shared library, or to verify a recompiled DLL is being loaded.

Syntax

cmd
listdlls [-r] [-u] [-v] [-d dllname] [process | PID]

Output: (none — exits 0 on success)

Essential options

SwitchMeaning
-rShow DLLs that were relocated (loaded at a non-preferred base)
-uOnly unsigned DLLs (essential for malware triage)
-vVerbose — include version info
-d dllnameFind which processes have loaded a specific DLL

What's loaded by a PID

cmd
listdlls -accepteula -v 7890

Output:

yaml
ListDLLs v3.2 - Listing DLLs

myapp.exe pid: 7890
Command line: "C:\Program Files\MyApp\myapp.exe" --quiet

Base                Size      Version         Path
0x00007ff60a000000  0x42000   1.4.2.0         C:\Program Files\MyApp\myapp.exe
                              Publisher:      Acme Software Inc.
                              Description:    MyApp
0x00007ffe1f000000  0x1ed000  10.0.22621.1    C:\Windows\System32\ntdll.dll
                              Publisher:      Microsoft Windows
0x00007ffe1e500000  0xb6000   10.0.22621.1    C:\Windows\System32\KERNEL32.DLL
0x00007ffe1c200000  0x312000  10.0.22621.1    C:\Windows\System32\KERNELBASE.dll
0x00007ffe17000000  0x88000   2.4.0.0         C:\Program Files\MyApp\plugins\authz.dll
                              Publisher:      Acme Software Inc.

Which processes have loaded a specific DLL

-d is the inverse query — useful for "is this AV product hooked into my service?".

cmd
listdlls -accepteula -d defender.dll

Output:

yaml
explorer.exe pid: 3456
  0x00007ffe0a000000  0xc8000   Defender.dll

chrome.exe pid: 6124
  0x00007ffe0a000000  0xc8000   Defender.dll

myapp.exe pid: 7890
  0x00007ffe0a000000  0xc8000   Defender.dll

Find unsigned DLLs loaded into a process

Critical malware-triage move — an unsigned DLL inside a signed Microsoft process is a strong injection indicator.

cmd
listdlls -accepteula -u 7890

Output:

yaml
myapp.exe pid: 7890

Base               Size     Path
0x00000000601f0000 0x42000  C:\Users\alicedev\AppData\Local\Temp\suspicious.dll
                            Verified: Unsigned

Common pitfalls (across the suite)

  1. The EULA dialog blocks scripted use — every tool needs -accepteula (or /AcceptEula for ProcMon) on first run on a given user account. Pre-set it system-wide by importing the registry: reg add "HKCU\Software\Sysinternals\<ToolName>" /v EulaAccepted /t REG_DWORD /d 1 /f.
  2. Most need elevation — handles owned by other users, services, kernel objects, and protected processes are invisible to a non-elevated prompt. Always run from an elevated cmd or PowerShell.
  3. AV alarms on the tools themselves — PsExec, PsKill, ProcDump, and Mimikatz-adjacent utilities trip every endpoint product. Maintain an allowlist for admin workstations and never copy these onto a regular user's machine.
  4. PsTools service residue on remote hosts — interrupted PsExec sessions leave psexesvc.exe running on the target. Clean up with sc \\target stop psexesvc && sc \\target delete psexesvc once a week on infrastructure servers.
  5. Tool versions diverge — the WinGet, Chocolatey, and live network share publish at different cadences. If autorunsc is missing a category you expected, you may be on an older build; the live share at \\live.sysinternals.com\tools\ is always current.
  6. ProcMon filters are stored per-user — a saved .pmc filter file is portable, but the default filters live in HKCU\Software\Sysinternals\Process Monitor. Use /LoadConfig to guarantee deterministic captures across machines.

Real-world recipes

"What has this file open?" — three answers

The single most common Sysinternals question. Handle is the canonical tool, but on modern Windows the in-box openfiles and PowerShell's Get-Process | Where-Object can sometimes substitute.

cmd
rem Handle (best)
handle -accepteula -nobanner C:\path\to\locked.dll

rem In-box openfiles (must be enabled first: openfiles /local on, then reboot)
openfiles /query /v | findstr /i "locked.dll"

rem PowerShell — slower, but no extra binary required
Get-Process | Where-Object { $_.Modules.FileName -match 'locked.dll' } | Select-Object Name, Id

Output (Handle):

lua
explorer.exe        pid: 3456   type: File   348: C:\path\to\locked.dll
myapp.exe           pid: 7890   type: File   9D4: C:\path\to\locked.dll

"Capture every file touched during install"

Use ProcMon to record what an installer does. The /Runtime flag self-terminates so the script can move on.

cmd
@echo off
md C:\Traces 2>NUL
procmon /AcceptEula /Quiet /Minimized /BackingFile C:\Traces\install.pml /Runtime 300
start /wait installer.exe /silent
procmon /Terminate
procmon /OpenLog C:\Traces\install.pml /SaveAs C:\Traces\install.csv
echo Trace saved to C:\Traces\install.csv

Output:

css
Trace saved to C:\Traces\install.csv

"Daily autoruns snapshot, alert on change"

Use autorunsc + fc for a poor-man's HIDS — alert any time a new autostart entry appears.

cmd
@echo off
setlocal
set DATEKEY=%DATE:~10,4%%DATE:~4,2%%DATE:~7,2%
set OUT=C:\IR\autoruns_%DATEKEY%.csv
set PREV=C:\IR\autoruns_prev.csv

autorunsc -accepteula -a * -c -h -s -nobanner > "%OUT%"
if exist "%PREV%" (
    fc /n "%PREV%" "%OUT%" > C:\IR\diff_%DATEKEY%.txt
    findstr /R "^\*\*\*\*\* " C:\IR\diff_%DATEKEY%.txt > NUL
    if not errorlevel 1 (
        echo Autoruns changed - see C:\IR\diff_%DATEKEY%.txt
    )
)
copy /Y "%OUT%" "%PREV%" > NUL

Output:

code
Autoruns changed - see C:\IR\diff_20260524.txt

"Run a one-off command as SYSTEM"

The local-SYSTEM shell trick — useful for resetting permissions on protected directories or reading TrustedInstaller-owned keys.

cmd
psexec -s -i -accepteula reg query "HKLM\SECURITY"

Output:

sql
(SYSTEM-owned subkeys printed; same query as administrator returns "Access is denied.")
HKEY_LOCAL_MACHINE\SECURITY\Cache
HKEY_LOCAL_MACHINE\SECURITY\Policy
HKEY_LOCAL_MACHINE\SECURITY\Policy\Accounts
...

"List every unsigned DLL in every running process"

A wider malware sweep — combine pslist for PIDs and listdlls -u per process. Slow but thorough.

cmd
for /f "skip=8 tokens=2" %P in ('pslist -accepteula -nobanner') do (
    listdlls -accepteula -u -nobanner %P 2>NUL | findstr /R "Unsigned 0x"
)

Output:

yaml
myapp.exe pid: 7890
  0x00000000601f0000 0x42000  C:\Users\alicedev\AppData\Local\Temp\suspicious.dll  Verified: Unsigned
chrome.exe pid: 6124
  0x00000000700a0000 0x18000  C:\Program Files\Acme\plugin.dll                     Verified: Unsigned

"Push a script to 50 machines and collect output"

PsExec's parallel @file mode with capture redirection.

cmd
psexec @servers.txt -u DOMAIN\alicedev -h -accepteula systeminfo > C:\IR\sysinfo_all.txt 2>&1
findstr /B "Host Name" C:\IR\sysinfo_all.txt

Output:

yaml
Host Name:                 MYHOST01
Host Name:                 MYHOST02
Host Name:                 MYHOST03
...

Tips

Sysinternals tools are stateless and per-binary — copying just handle.exe to a target is enough, you don't need the whole suite. Keep a small "field kit" with handle, procexp, procmon, psexec, and autoruns on a USB drive for on-site triage.

ProcMon's binary .pml files compress at roughly 10:1 with 7-Zip. Always compress before emailing a trace to a colleague — a 500 MB raw log becomes a 50 MB attachment.

The psping utility (also Sysinternals) measures TCP/UDP latency much more accurately than ping — useful when troubleshooting application connectivity between hosts where ICMP is blocked.

Sources