PowerShell one-liners for sysadmins

These are the commands admins paste daily. One rule governs the whole sheet and it is the reason the wording above each command says verified: everything here runs as written in Windows PowerShell 5.1 and PowerShell 7 on Windows. CIM, the registry and the built-in modules cover nearly every row — the two exceptions are marked in the table itself: the Security-log row (logon events) runs elevated with auditing enabled, and the Active Directory row needs the AD module (RSAT) or a domain controller.

Three conventions keep the table short. Drive-type filters (DriveType=3) restrict inventory queries, @{n=...;e={...}} turns raw bytes into readable numbers, and everything that changes a machine shows its -WhatIf first so the destructive commands never surprise you — details below the table.

One-liners by task

All commands verified against Microsoft Learn cmdlet references; each one is a single paste into an ordinary (non-elevated, where marked) PowerShell window. Reads never prompt; writes and Security-log rows state when they need elevation.
TaskCommandOutput hints
Disk space, rounded GBGet-CimInstance Win32_LogicalDisk -Filter "DriveType=3" | Select-Object DeviceID, @{n="SizeGB";e={[math]::Round($_.Size/1GB,1)}}, @{n="FreeGB";e={[math]::Round($_.FreeSpace/1GB,1)}}One row per local fixed disk; DriveType=4 for mapped network drives, no filter for everything
Largest files under a pathGet-ChildItem -Path C:\ -Recurse -File -ErrorAction SilentlyContinue | Sort-Object Length -Descending | Select-Object -First 10 FullName, @{n="MB";e={[math]::Round($_.Length/1MB)}}Slow over a full volume; narrow -Path, tune -First. Permission errors are skipped silently
Files older than 30 daysGet-ChildItem -Path C:\Users\demo\Downloads -Recurse -File -ErrorAction SilentlyContinue | Where-Object LastWriteTime -lt (Get-Date).AddDays(-30) | Select-Object FullName, LastWriteTimeThe age window is the only knob: -lt + AddDays(-30) gets everything untouched for a month; add -First 20 after -ErrorAction to cap output
Files changed in the last 24 hoursGet-ChildItem -Path C:\Users\demo\Documents -Recurse -File -ErrorAction SilentlyContinue | Where-Object LastWriteTime -gt (Get-Date).AddHours(-24) | Select-Object FullName, LastWriteTimeMirror of the age row: -gt with AddHours(-24) means newer than a day; swap in AddDays(-3) for a longer window
Folder size in MB[math]::Round((Get-ChildItem -Path C:\Users\demo\Downloads -Recurse -File -ErrorAction SilentlyContinue | Measure-Object Length -Sum).Sum / 1MB, 1)One number, no records; Measuring -Sum folds the whole scan into a single pipe object
Copy a folder treeCopy-Item -Path C:\src\web\* -Destination C:\dst\web -Recurse -ForceThe wildcard copies the contents of web into the destination folder; without it, Copy-Item names the new folder after the source
Zip a folderCompress-Archive -Path C:\src\web -DestinationPath C:\dst\web-backup.zip -Force-Force overwrites an existing archive; .zip only — other formats need external tools
Unzip an archiveExpand-Archive -Path C:\dst\web-backup.zip -DestinationPath C:\dst\web-restored -ForceRequires the .zip of the compression row; -Force merges into an existing release
Running servicesGet-Service | Where-Object Status -eq "Running" | Sort-Object Name | Select-Object Name, DisplayNameFor a statistical view: Get-Service | Group-Object Status | Select-Object Name, Count
Services set to auto-startGet-Service | Where-Object StartType -eq "Automatic" | Select-Object Name, StartType, StatusStartType shows the configured mode, not the current state
Auto services that are not runningGet-Service | Where-Object { $_.StartType -eq "Automatic" -and $_.Status -ne "Running" } | Select-Object Name, DisplayName, StatusThe script-block form is required when you compare two properties; this is the 'quietly failed startup' catch-all
Change a service startup typeSet-Service -Name Spooler -StartupType Automatic -WhatIfAdmin required; drop -WhatIf to apply. Values: Automatic, AutomaticDelayedStart, Manual, Disabled
Top-memory processesGet-Process | Sort-Object WorkingSet64 -Descending | Select-Object -First 10 Name, Id, @{n="MemMB";e={[math]::Round($_.WorkingSet64/1MB)}}Swap WorkingSet64 for CPU to sort by processor time
Stop a process safelyStop-Process -Name notepad -WhatIf-WhatIf shows exactly what would be killed; by PID: Stop-Process -Id 2748 -WhatIf
Up network adaptersGet-NetAdapter | Where-Object Status -eq "Up" | Select-Object Name, InterfaceDescription, LinkSpeed, MacAddressWindows-only module; Get-NetAdapterStatistics gives traffic counters under the same filter
IPv4 addresses per adapterGet-NetIPAddress -AddressFamily IPv4 | Where-Object InterfaceAlias -notlike "*Loopback*" | Select-Object InterfaceAlias, IPAddress, PrefixLengthUse -AddressFamily IPv6 for the v6 side; -notlike keeps the loopback out
Flush the DNS cacheClear-DnsClientCacheThe PowerShell twin of ipconfig /flushdns; silent on success
Look up a nameResolve-DnsName example.com | Select-Object Name, Type, IPAddressReads the same resolver as nslookup; append -Type MX, -Type TXT for other record types
Port reachability testTest-NetConnection -ComputerName example.com -Port 443 -InformationLevel DetailedLook for TcpTestSucceeded: True plus Latency; Windows-only in PowerShell 7
Listening ports and their processGet-NetTCPConnection -State Listen | Select-Object LocalAddress, LocalPort, @{n="Proc";e={(Get-Process -Id $_.OwningProcess).ProcessName}}The netstat -ano equivalent; -OwningProcess maps the port to its PID
Connections to one remote portGet-NetTCPConnection -RemotePort 443 -ErrorAction SilentlyContinue | Select-Object LocalAddress, LocalPort, RemoteAddress, RemotePort, StateFiltering on the remote side is what shows 'who on this box talks to 443'; no match is empty output, not an error
UDP listenersGet-NetUDPEndpoint | Select-Object LocalAddress, LocalPort, OwningProcessnetstat's UDP lines are text; this is the object view, and Get-NetTCPConnection cannot see UDP at all
Quick ping testTest-Connection -ComputerName srv01 -Count 1 -QuietTrue/False only — the row for scripts; Test-NetConnection adds TCP when you need both
Recent errors in the System logGet-WinEvent -FilterHashtable @{LogName="System"; Level=2,3} -MaxEvents 20 | Select-Object TimeCreated, Id, ProviderName, LevelDisplayNameLevel 2 is Error, 3 Warning; widen a single record with Format-List *
Errors only, Application logGet-WinEvent -FilterHashtable @{LogName="Application"; Level=2} -MaxEvents 20 | Select-Object TimeCreated, Id, ProviderNameLevel=2 drops the warnings noise; Level=1,2,3 covers critical/error/warning
Events since a given timeGet-WinEvent -FilterHashtable @{LogName="System"; StartTime=(Get-Date).AddDays(-1)} -MaxEvents 20 | Select-Object TimeCreated, Id, ProviderNameStartTime is an accepted FilterHashtable key — the 'what broke this morning' query; System log needs no elevation
Shutdown and restart historyGet-WinEvent -FilterHashtable @{LogName="System"; Id=1074} -MaxEvents 10 | Select-Object TimeCreated, @{n="Type";e={$_.Properties[4].Value}}1074 logs who requested the shutdown; Properties[4] is the event's Type field (restart, shutdown, ...) — use -Credential for remote hosts
Logon eventsGet-WinEvent -FilterHashtable @{LogName="Security"; Id=4624} -MaxEvents 20 | Select-Object TimeCreated, @{n="User";e={$_.Properties[5].Value}}, @{n="LogonType";e={$_.Properties[8].Value}}Security reads need elevation and logon auditing enabled; LogonType 10 is RDP (2 interactive, 3 network)
Last boot and uptimeGet-CimInstance Win32_OperatingSystem | Select-Object LastBootUpTime, @{n="UpDays";e={[int]((Get-Date)-$_.LastBootUpTime).TotalDays}}LastBootUpTime is CIM datetime; cast [datetime] where a date comparison needs it
Uptime in one line$up=(Get-Date)-(Get-CimInstance Win32_OperatingSystem).LastBootUpTime; "{0}d {1}h {2}m" -f $up.Days, $up.Hours, $up.MinutesSame source as the last-boot row, packed into a single short string; the -f format operator is what rounds it
Pending reboot check@(Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending"; Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired") -contains $trueTrue when either the component-servicing or the Windows Update key marks a restart pending; both are documented checks
Logon sessions on this machinequserquser.exe runs from PowerShell; page through a terminal server with quser /SERVER:srv01
Local usersGet-LocalUser | Select-Object Name, Enabled, LastLogon, PrincipalSourceLocal accounts only — domain users never appear; PrincipalSource says Local vs Active Directory (Windows 10/Server 2016+)
Local group membersGet-LocalGroupMember -Group Administrators | Select-Object Name, ObjectClass, PrincipalSource-Group or -Name name the group; nested groups show ObjectClass Group, members show User
Enabled domain usersGet-ADUser -Filter "Enabled -eq $true" -Properties LastLogonDate | Select-Object SamAccountName, LastLogonDateActiveDirectory module required (RSAT on clients, or run on a domain controller); LastLogonDate is time-zone converted, LastLogon is not
PrintersGet-Printer | Select-Object Name, DriverName, PortName, PrinterStatusPrinterStatus is the spooler's view of the queue — the quick 'which printer is broken' read
Scheduled tasks ready to runGet-ScheduledTask | Where-Object State -eq "Ready" | Select-Object TaskName, TaskPath, StateReady is the enabled-and-eligible state; TaskPath is the library folder the task lives in
Installed hotfixesGet-HotFix -ErrorAction SilentlyContinue | Sort-Object InstalledOn -Descending | Select-Object HotFixID, Description, InstalledOnWindows Update / WU history patches; stream it off a remote box with -ComputerName srv01
Installed softwareGet-ItemProperty "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*","HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" | Where-Object DisplayName | Select-Object DisplayName, DisplayVersion, Publisher | Sort-Object DisplayNameFull walkthrough in /guides/powershell-list-installed-software/
Export any listing to CSVGet-Service | Where-Object Status -eq "Running" | Export-Csv -NoTypeInformation -Path .\running-services.csvPipe from the start of any row here; -NoTypeInformation keeps 5.1 files clean

Running commands safely

Preview before you commit — -WhatIf works on every cmdlet that changes something
Stop-Process -Name notepad -WhatIf
Remove-Item -Path C:\Users\demo\AppData\Local\Temp\* -Recurse -WhatIf
Set-Service -Name Spooler -StartupType Disabled -WhatIf
Restart-Computer -WhatIf

The two safety levers in PowerShell terms

-WhatIf
prints what the command would do and does nothing — supported by Stop-Process, Remove-Item, Set-Service, Restart-Computer and most modifying cmdlets
-Confirm / $ConfirmPreference
asks before acting; pipe Get-Command to a filter over the Parameters dictionary to list which cmdlets of a module support -WhatIf
ValidateSet
restricts a parameter's accepted values before anything runs — Set-Service -StartupType rejects anything outside Automatic, AutomaticDelayedStart, Manual, Disabled
Read-only rule
inventory cmdlets (Get-*) never change the machine: Get-CimInstance, Get-Service, Get-Process, Get-WinEvent and the Get-Net* family are safe to run anywhere
The rows that write — Set-Service, Stop-Process, Remove-Item — need an elevated prompt, and so do Stop-Process -Force on other users' processes. Test on a lab box when the target is a fleet: -WhatIf proves the pipeline, and -Confirm protects the first run. For one pattern across many machines, wrap the row in Invoke-Command -ComputerName srv01, srv02 -ScriptBlock { ... }.

Notes on the rows

When a row needs more than one read

FAQ

How do I test a command without running it?

Add -WhatIf. It works on Stop-Process, Remove-Item, Set-Service, Restart-Computer and most cmdlets that modify the machine — the output tells you exactly what would have happened. For parameter validation, ValidateSet attributes catch bad values before anything runs: Set-Service -StartupType rejects any string outside Automatic, AutomaticDelayedStart, Manual and Disabled. The safe habit: two dashes before the first real run (-WhatIf, then -Confirm).

Do these one-liners require administrator rights?

Only the write rows. Get-CimInstance, Get-Service, Get-Process, Get-WinEvent, Get-NetAdapter, Get-NetIPAddress, Clear-DnsClientCache, Test-NetConnection and Export-Csv all run from a normal prompt. Set-Service, Stop-Process -Force on other users' processes, Remove-Item of system paths and the DISM-style cleanup need elevation.

Can I run the same commands against many computers at once?

Yes, with Invoke-Command when WinRM is reachable: Invoke-Command -ComputerName srv01, srv02 -ScriptBlock { Get-Service | Where-Object Status -eq 'Running' }. The -ComputerName parameter of Get-WinEvent also works for event logs without PowerShell remoting, and Get-WinEvent with a plain CIM or registry query goes through the same CIM wiring.

Why is Get-CimInstance used and not Get-WmiObject?

Get-WmiObject is the legacy WMI wrapper: retained in 5.1, not available in PowerShell 7. Get-CimInstance uses CIM (WS-Man) and works identically in 5.1 and 7, which is why every inventory command in this sheet uses it. For the same classes (Win32_LogicalDisk, Win32_OperatingSystem, Win32_Service) the output is the same; the console format differs slightly.