6:45 PM, Friday. A ticket lands: “Something’s wrong with SRV-FILE01, users are complaining about slowness.” You don’t have RDP handy, just WinRM access, and five minutes until a call where you need to say something concrete. Opening a dozen windows — System Properties GUI, Device Manager, “About” — is a luxury you don’t have. You need one screen that answers every question at once.
Here’s the script I keep bookmarked for exactly these moments. Not a toy one-liner — a working version that answers not just “what system is this” but “is it time to panic”: how much disk space is left, when updates were last applied, whether the server is stuck waiting on a pending reboot.
The full script
PowerShell
$os = Get-CimInstance Win32_OperatingSystem
$cs = Get-CimInstance Win32_ComputerSystem
$lastHotfix = Get-HotFix | Sort-Object InstalledOn -Descending | Select-Object -First 1
$rebootPending = Test-Path "HKLM:SOFTWAREMicrosoftWindowsCurrentVersionComponent Based ServicingRebootPending"
[PSCustomObject]@{
"Computer name" = $env:COMPUTERNAME
"Domain / workgroup" = if ($cs.PartOfDomain) { $cs.Domain } else { "$($cs.Workgroup) (not domain-joined)" }
"IP address" = (Get-NetIPAddress -AddressFamily IPv4 -AddressState Preferred -ErrorAction SilentlyContinue | Select-Object -First 1).IPAddress
"Windows version" = (Get-ItemProperty "HKLM:SOFTWAREMicrosoftWindows NTCurrentVersion").ProductName
"Install date" = (Get-Date "1970-01-01").AddSeconds((Get-ItemProperty "HKLM:SOFTWAREMicrosoftWindows NTCurrentVersion").InstallDate)
"Uptime" = (New-TimeSpan -Start $os.LastBootUpTime)
"Last update" = if ($lastHotfix) { "$($lastHotfix.HotFixID) — $($lastHotfix.InstalledOn.ToShortDateString())" } else { "no data" }
"Reboot pending" = $rebootPending
} | Format-List
Write-Host "`nDisk space:" -ForegroundColor Cyan
Get-PSDrive -PSProvider FileSystem | Where-Object { $_.Used -gt 0 } | ForEach-Object {
$freeGB = [math]::Round($_.Free / 1GB, 1)
$totalGB = [math]::Round(($_.Used + $_.Free) / 1GB, 1)
$pctFree = [math]::Round(($_.Free / ($_.Used + $_.Free)) * 100, 1)
"{0}: {1} GB free of {2} GB ({3}%)" -f $_.Name, $freeGB, $totalGB, $pctFree
}
On a real server the output looks something like this:
Computer name : SRV-FILE01
Domain / workgroup : contoso.local
IP address : 10.20.4.15
Windows version : Windows Server 2022 Standard
Install date : 2/3/2023 9:14:02 AM
Uptime : 47.03:12:41.5012340
Last update : KB5040442 — 9/8/2025
Reboot pending : True
Disk space:
C: 4.2 GB free of 120 GB (3.5%)
D: 812.6 GB free of 2000 GB (40.6%)
Now the call can start with facts, not “let me check.” Drive C: is 96.5% full and the server has been waiting two weeks for a post-patch reboot — that’s your first working theory for the slowdown, before you’ve even opened Task Manager.
How it works
The script does exactly one “expensive” thing — it hits CIM/WMI for Win32_OperatingSystem and Win32_ComputerSystem — and stashes the result in variables so it doesn’t re-query for every field. Everything after that is just assembling the report:
- Domain / workgroup:
$cs.PartOfDomainis a boolean. If the server isn’t domain-joined, the script flags it right away instead of silently showing an empty field — a frequent reason a “required” GPO never applied. - Last update:
Get-HotFixpulls the list of installed patches from the Windows Update log; sorting by date and taking the first entry gives you the most recent one. A date three months old here isn’t a diagnosis by itself, but it’s a reason to ask about WSUS/Intune. - Reboot pending:
RebootPendingisn’t a made-up field — it’s a real registry key that Windows creates after installing certain updates and doesn’t remove until the next restart. A huge share of “unexplained slowness” turns out to be a server that’s been sitting for two months in a post-patch transitional state. - Disk space:
Get-PSDrive -PSProvider FileSystemreturns every mounted volume, including network drives — theWhere-Object { $_.Used -gt 0 }filter strips out empty/unreachable ones so they don’t clutter the output.
Remotely, across the whole fleet
The point of this script isn’t to run it by hand on one machine at a time. Wrap it in Invoke-Command and get the same summary from dozens of servers at once:
PowerShell
# servers.txt — one server name per line
$servers = Get-Content servers.txt
Invoke-Command -ComputerName $servers -ScriptBlock {
# the full script body goes here
} | Select-Object PSComputerName, "Reboot pending", "Last update" |
Sort-Object "Reboot pending" -Descending |
Format-Table -AutoSize
Sorting by “Reboot pending” isn’t an accident: it floats every problem server to the top of the table, instead of getting lost among thirty rows that all say “fine.”
Three ways to take this further
- Save it as a
.ps1and schedule it via Task Scheduler — the Windows-world equivalent of asystemd.timer— logging output to a file. That way, by the time a complaint arrives, you already have history, not just a current snapshot. - Export for a ticket: swap the final
Format-Listfor| ConvertTo-Html -Head "— you get a page you won’t be embarrassed to attach to a ticket.Report $env:COMPUTERNAME " | Out-File report.html - Alert threshold: add a simple check at the end and let the script decide whether to notify Zabbix/Telegram itself:
if ($pctFree -lt 10) { Send-MailMessage ... }— don’t wait for the disk to hit zero on its own.
The difference between an “admin” and an “architect” is extremely concrete here: the admin opens RDP and clicks through tabs; the architect runs one command and already knows the answer before the chat with their manager even opens.
Tags: #powershell #windows #sysadmin #automation #monitoring
Want to become tomorrow’s architect instead of just an admin? This article is only the tip of the iceberg. On our Telegram channel “Admin Future” we publish systems-thinking guides, ready-to-use scripts, AI tips, and checklists every day that you won’t find on Google. Subscribe and become the expert in the room: Admin Future



