A healthy Windows Server is not maintained by one magic command. It comes from collecting the right evidence, spotting change early and making controlled decisions before a warning becomes an outage.
These ten PowerShell commands form a practical health-check toolkit for Windows Server administrators. Most of the examples are deliberately read-only: they help you inspect performance, storage, services, security and system integrity without immediately changing production. Run them from an elevated PowerShell session where required, test them on your Windows Server version and understand the output before taking remedial action.
Before you begin: PowerShell makes administration fast, but it also makes large-scale mistakes fast. Confirm your target server, preserve logs, verify backups and use an approved maintenance window before running repair, cleanup or restart commands.
Windows Server PowerShell commands at a glance
| Command | What it tells you | Change risk |
|---|---|---|
Get-ComputerInfo |
Operating-system, build and server identity | Read-only |
Get-Volume |
Volume health, capacity and free space | Read-only |
Get-WinEvent |
Recent errors and warnings | Read-only |
Get-Process |
Processes consuming CPU and memory | Read-only |
Get-CimInstance Win32_Service |
Automatic services that are not running | Read-only |
Get-NetTCPConnection |
Listening ports and established connections | Read-only |
Get-NetFirewallProfile |
Effective Windows Firewall profile state | Read-only |
Get-MpComputerStatus |
Microsoft Defender health and signature age | Read-only |
Test-ComputerSecureChannel |
Domain trust health on member servers | Read-only unless -Repair is added |
Repair-WindowsImage |
Component-store corruption and cleanup | Scan is read-only; repair and cleanup change the server |
1. Get-ComputerInfo: establish exactly what you are managing
Start every investigation by confirming the server name, operating-system edition, build and last boot time. It prevents a surprisingly common mistake: troubleshooting the wrong machine or applying advice written for a different Windows Server release.
Get-ComputerInfo |
Select-Object CsName,
WindowsProductName,
WindowsVersion,
OsBuildNumber,
OsArchitecture,
OsLastBootUpTime
Record this output with the incident notes. The build number helps you verify patch level and known issues, while the boot time tells you whether a recent restart coincides with the fault. If OsLastBootUpTime is not returned on an older build, use Get-CimInstance Win32_OperatingSystem and inspect LastBootUpTime.
2. Get-Volume: find capacity pressure before services fail
Low disk space can break updates, stop databases, prevent logging and make otherwise healthy applications unstable. This view turns the raw byte values into useful gigabytes and a percentage of free capacity.
Get-Volume |
Where-Object DriveLetter |
Select-Object DriveLetter,
FileSystemLabel,
HealthStatus,
@{Name='SizeGB'; Expression={[math]::Round($_.Size / 1GB, 1)}},
@{Name='FreeGB'; Expression={[math]::Round($_.SizeRemaining / 1GB, 1)}},
@{Name='FreePercent'; Expression={
if ($_.Size) {[math]::Round(($_.SizeRemaining / $_.Size) * 100, 1)}
}} |
Sort-Object FreePercent
Treat fast, unexplained growth as an incident rather than merely deleting files. Check application logs, database files, crash dumps, backup staging areas and retention policies. Never remove component-store or database files manually.
3. Get-WinEvent: surface the last 24 hours of real evidence
Event Viewer is invaluable, but PowerShell makes it easier to collect a focused timeline. Filtering at source with -FilterHashtable is much faster than retrieving an entire log and filtering afterwards.
$since = (Get-Date).AddHours(-24)
Get-WinEvent -FilterHashtable @{
LogName = 'System', 'Application'
Level = 1, 2, 3
StartTime = $since
} -ErrorAction SilentlyContinue |
Select-Object TimeCreated, LogName, Id, ProviderName, LevelDisplayName, Message |
Sort-Object TimeCreated -Descending |
Select-Object -First 100
Level 1, 2 and 3 represent Critical, Error and Warning events. One warning does not necessarily reveal the cause; look for clusters, repeated event IDs and events immediately before the first user-visible symptom. Export evidence before clearing any log.
4. Get-Process: identify resource-heavy processes
This command provides a quick view of processes with the largest cumulative CPU time and working set.
Get-Process |
Sort-Object CPU -Descending |
Select-Object -First 15 Name,
Id,
@{Name='CPUSeconds'; Expression={[math]::Round($_.CPU, 1)}},
@{Name='MemoryMB'; Expression={[math]::Round($_.WorkingSet64 / 1MB, 1)}},
StartTime
The CPU value is total processor time since that process started, not the current CPU percentage. Use it to identify candidates, then confirm live behaviour with Task Manager, Resource Monitor or Get-Counter. Do not terminate a process solely because it appears near the top of this list.
5. Get-CimInstance Win32_Service: find failed automatic services
A stopped automatic service can explain failed logons, unreachable applications, missed backups or monitoring gaps. CIM provides a consistent view of both current state and configured start mode.
Get-CimInstance Win32_Service |
Where-Object {
$_.StartMode -eq 'Auto' -and
$_.State -ne 'Running'
} |
Select-Object Name, DisplayName, State, StartMode, ExitCode |
Sort-Object DisplayName
Some automatic services use trigger-start behaviour and may legitimately stop when idle. Check the service role, dependencies and event logs before restarting it. If a service repeatedly stops, restarting it restores availability but does not resolve the root cause.
6. Get-NetTCPConnection: review listening ports and connections
Unexpected listening ports, connections to unfamiliar addresses or a sudden connection surge deserve investigation. This example links each listening port to its owning process.
Get-NetTCPConnection -State Listen |
Sort-Object LocalPort |
Select-Object LocalAddress,
LocalPort,
OwningProcess,
@{Name='ProcessName'; Expression={
(Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).ProcessName
}}
Compare the result with the server’s documented role and approved software. A listening port is not automatically malicious, and closing it without understanding the dependency can cause an outage. For a specific remote service, use Test-NetConnection server.example.com -Port 443.
7. Get-NetFirewallProfile: confirm the active firewall posture
Windows Firewall should remain enabled unless another documented control replaces it. Query the active policy store so you see the effective settings applied locally and through Group Policy.
Get-NetFirewallProfile -PolicyStore ActiveStore |
Select-Object Name,
Enabled,
DefaultInboundAction,
DefaultOutboundAction,
LogAllowed,
LogBlocked,
LogFileName
Pay particular attention to a disabled Domain profile, unexpected inbound defaults and missing blocked-traffic logging. Do not enable or remove rules in bulk without confirming remote-management access and application requirements.
8. Get-MpComputerStatus: verify Microsoft Defender health
Where Microsoft Defender Antivirus is the active protection platform, this command shows whether protection is enabled, signatures are current and scans are completing.
Get-MpComputerStatus |
Select-Object AMServiceEnabled,
AntivirusEnabled,
RealTimeProtectionEnabled,
BehaviorMonitorEnabled,
AntivirusSignatureLastUpdated,
AntivirusSignatureAge,
QuickScanAge,
FullScanAge
Investigate disabled real-time protection or stale signatures immediately. If Defender is intentionally in passive mode because another supported security product is installed, document that architecture rather than treating the value in isolation. To request current signatures, use Update-MpSignature during an appropriate maintenance window.
9. Test-ComputerSecureChannel: check domain trust safely
Use this on a domain-member server when users see trust errors or domain authentication behaves inconsistently.
Test-ComputerSecureChannel -Verbose
A result of True indicates that the member server’s secure channel is working. Do not use this test on a domain controller: Microsoft notes that it can return false-positive errors there. The -Repair switch makes a change and may require credentials, so diagnose DNS, time synchronisation and domain-controller reachability before considering it.
10. Repair-WindowsImage: check Windows component health
Component-store corruption can cause update failures and damaged Windows features. Begin with a scan rather than jumping straight to repair.
Repair-WindowsImage -Online -ScanHealth
If corruption is reported and you have a tested backup, suitable repair source and maintenance window, the controlled remediation is:
Repair-WindowsImage -Online -RestoreHealth
For component-store housekeeping, analyse the store first with DISM.exe /Online /Cleanup-Image /AnalyzeComponentStore. If cleanup is recommended, Repair-WindowsImage -Online -StartComponentCleanup removes superseded components. Avoid adding -ResetBase casually: Microsoft warns that installed updates cannot be uninstalled after that operation.
A reusable weekly health snapshot
The most useful health check is consistent and timestamped. The following read-only script creates a folder and exports a small evidence pack that can be compared week to week or attached to a support ticket.
$stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
$reportPath = "C:\Admin\HealthChecks\$env:COMPUTERNAME-$stamp"
New-Item -ItemType Directory -Path $reportPath -Force | Out-Null
Get-ComputerInfo |
Select-Object CsName, WindowsProductName, WindowsVersion,
OsBuildNumber, OsLastBootUpTime |
Export-Csv "$reportPath\computer.csv" -NoTypeInformation
Get-Volume |
Select-Object DriveLetter, FileSystemLabel, HealthStatus,
Size, SizeRemaining |
Export-Csv "$reportPath\volumes.csv" -NoTypeInformation
Get-CimInstance Win32_Service |
Where-Object {$_.StartMode -eq 'Auto' -and $_.State -ne 'Running'} |
Select-Object Name, DisplayName, State, StartMode, ExitCode |
Export-Csv "$reportPath\stopped-auto-services.csv" -NoTypeInformation
Get-WinEvent -FilterHashtable @{
LogName='System','Application'
Level=1,2,3
StartTime=(Get-Date).AddDays(-7)
} -ErrorAction SilentlyContinue |
Select-Object TimeCreated, LogName, Id, ProviderName,
LevelDisplayName, Message |
Export-Csv "$reportPath\events.csv" -NoTypeInformation
Get-NetTCPConnection -State Listen |
Select-Object LocalAddress, LocalPort, OwningProcess |
Export-Csv "$reportPath\listening-ports.csv" -NoTypeInformation
Write-Host "Health snapshot saved to $reportPath"
This is a starting point, not a complete monitoring platform. A weekly export will not alert you when a disk fills at 2am, confirm that a backup can be restored or correlate a security event across multiple systems. Production servers still need central monitoring, patch governance, tested recovery and human review.
How often should these checks run?
- Continuously: service availability, CPU, memory, storage, backup status, security alerts and certificate expiry.
- Daily: failed backups, critical events, Defender status, low storage and stopped business-critical services.
- Weekly: trend review, listening ports, failed automatic services, update status and capacity forecasts.
- Monthly: restore testing, privileged-access review, firewall-rule review, patch compliance and documentation.
- After every incident: preserve evidence, identify the root cause, record the fix and improve the monitoring rule that should detect it next time.
Commands help; accountable management prevents incidents
PowerShell is excellent for finding facts quickly, but a clean and secure server depends on what happens between command runs: supported software, controlled change, sensible hardening, monitored backups, patch testing and a named person responsible for acting on warnings.
If your team is spending too much time checking servers manually, Astley Digital can manage the monitoring, patching, backup, security and day-to-day administration for you. Explore our managed server services, read our Windows Server troubleshooting guide, or talk to our team about the systems you need to protect.
Official command references
Command availability and behaviour vary by Windows Server and PowerShell version. Check the relevant Microsoft documentation before using an example in production:
Ready for a clearer technology plan?
Tell us what is slowing your organisation down. We will help you identify the practical next step.