PowerShell is the most powerful administration tool for Windows Server, and since PowerShell 7, it also runs on Linux and macOS. For anyone managing Windows infrastructure — servers, Active Directory, Exchange, or Azure — mastering PowerShell is not optional. It is essential.
This guide covers the most important commands, scripts, and techniques that Windows Server administrators use every day.
Getting Started with PowerShell
# Check PowerShell version
$PSVersionTable.PSVersion
# Get help for any command
Get-Help Get-Process -Full
# Update help files
Update-Help -Force
# Find commands related to a topic
Get-Command *service*
Get-Command -Module ActiveDirectory
PowerShell vs CMD vs Bash
| Task | CMD | PowerShell |
|---|---|---|
| List files | dir | Get-ChildItem |
| Copy files | copy | Copy-Item |
| Find text | findstr | Select-String |
| Services | sc query | Get-Service |
| Processes | tasklist | Get-Process |
| Output to objects | Text only | Structured objects |
📚 PowerShell Foundations
- PowerShell 7.x Fundamentals — €18.90 — Modern PowerShell from the ground up
- Mastering PowerShell — €14.90 — Advanced techniques and patterns
- PowerShell Essentials for Windows Server 2025 — €7.90 — Server-focused quick reference
Server Management Essentials
# System information
Get-ComputerInfo | Select-Object CsName, OsName, OsVersion, CsTotalPhysicalMemory
# Check Windows services
Get-Service | Where-Object {$_.Status -eq 'Running'} | Sort-Object DisplayName
# Start/Stop/Restart services
Restart-Service -Name "W3SVC" -Force
Start-Service -Name "MSSQLSERVER"
Stop-Service -Name "Spooler"
# Check disk space on all drives
Get-PSDrive -PSProvider FileSystem | Select-Object Name,
@{N='Used(GB)';E={[math]::Round($_.Used/1GB,2)}},
@{N='Free(GB)';E={[math]::Round($_.Free/1GB,2)}},
@{N='Total(GB)';E={[math]::Round(($_.Used+$_.Free)/1GB,2)}}
# Check running processes sorted by memory usage
Get-Process | Sort-Object WorkingSet64 -Descending |
Select-Object -First 10 Name, Id,
@{N='Memory(MB)';E={[math]::Round($_.WorkingSet64/1MB,1)}}
# Event log — last 20 errors
Get-EventLog -LogName System -EntryType Error -Newest 20 |
Select-Object TimeGenerated, Source, Message
Active Directory Management
# Import the AD module
Import-Module ActiveDirectory
# Find a user
Get-ADUser -Identity "jsmith" -Properties *
# Search users by name
Get-ADUser -Filter "Name -like '*Johnson*'" | Select-Object Name, SamAccountName, Enabled
# Create a new user
New-ADUser -Name "Jane Doe" -SamAccountName "jdoe" `
-UserPrincipalName "jdoe@company.com" `
-GivenName "Jane" -Surname "Doe" `
-Department "Engineering" `
-AccountPassword (ConvertTo-SecureString "TempPass123!" -AsPlainText -Force) `
-Enabled $true -ChangePasswordAtLogon $true
# Disable inactive accounts (no login in 90 days)
$cutoff = (Get-Date).AddDays(-90)
Search-ADAccount -AccountInactive -DateTime $cutoff -UsersOnly |
Where-Object {$_.Enabled -eq $true} |
ForEach-Object {
Disable-ADAccount $_.SamAccountName
Write-Host "Disabled: $($_.Name)"
}
# List all groups a user belongs to
Get-ADPrincipalGroupMembership -Identity "jdoe" | Select-Object Name
# Find locked-out accounts
Search-ADAccount -LockedOut | Select-Object Name, SamAccountName, LastLogonDate
# Unlock an account
Unlock-ADAccount -Identity "jdoe"
# Export all users to CSV
Get-ADUser -Filter * -Properties Department, Title, EmailAddress |
Select-Object Name, SamAccountName, Department, Title, EmailAddress |
Export-Csv -Path "C:\Reports\all_users.csv" -NoTypeInformation
📚 Active Directory & Windows Server
- PowerShell for Active Directory — €22.90 — Automate AD management completely
- Active Directory Fundamentals — €9.90 — Understand AD architecture
- Windows Server 2025 Administration — €13.90 — Latest Windows Server guide
- Windows Server 2025: Manage with PowerShell — €14.90 — Server automation deep dive
Remote Administration
# Enable PowerShell Remoting (run on target server)
Enable-PSRemoting -Force
# Run a command on a remote server
Invoke-Command -ComputerName "Server01" -ScriptBlock {
Get-Service | Where-Object {$_.Status -eq 'Stopped' -and $_.StartType -eq 'Automatic'}
}
# Interactive remote session
Enter-PSSession -ComputerName "Server01"
# Run on multiple servers simultaneously
$servers = @("Web01", "Web02", "DB01", "App01")
Invoke-Command -ComputerName $servers -ScriptBlock {
[PSCustomObject]@{
Server = $env:COMPUTERNAME
Uptime = (Get-CimInstance Win32_OperatingSystem).LastBootUpTime
FreeRAM = [math]::Round((Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory/1MB, 2)
}
} | Format-Table
Automated Reporting Script
# Weekly server health report
function Get-ServerHealthReport {
param([string[]]$Servers)
$report = foreach ($server in $Servers) {
try {
Invoke-Command -ComputerName $server -ScriptBlock {
$os = Get-CimInstance Win32_OperatingSystem
$disk = Get-CimInstance Win32_LogicalDisk -Filter "DeviceID='C:'"
[PSCustomObject]@{
Server = $env:COMPUTERNAME
Status = "Online"
Uptime = ((Get-Date) - $os.LastBootUpTime).Days
CPULoad = (Get-CimInstance Win32_Processor).LoadPercentage
FreeRAM_GB = [math]::Round($os.FreePhysicalMemory/1MB, 1)
DiskFree_GB = [math]::Round($disk.FreeSpace/1GB, 1)
DiskFree_Pct = [math]::Round($disk.FreeSpace/$disk.Size*100, 0)
}
}
} catch {
[PSCustomObject]@{
Server = $server; Status = "OFFLINE"
Uptime = "N/A"; CPULoad = "N/A"
FreeRAM_GB = "N/A"; DiskFree_GB = "N/A"; DiskFree_Pct = "N/A"
}
}
}
$report | Format-Table -AutoSize
$report | Export-Csv "C:\Reports\health_$(Get-Date -f yyyyMMdd).csv" -NoTypeInformation
}
Get-ServerHealthReport -Servers "Web01","Web02","DB01"
Practical Automation Scripts
# Clean up old files (IIS logs older than 30 days)
Get-ChildItem "C:\inetpub\logs\LogFiles" -Recurse -File |
Where-Object {$_.LastWriteTime -lt (Get-Date).AddDays(-30)} |
Remove-Item -Force -Verbose
# Monitor a service and restart if stopped
$service = "W3SVC"
while ($true) {
$status = (Get-Service $service).Status
if ($status -ne 'Running') {
Write-Host "$(Get-Date): $service is $status — restarting..."
Start-Service $service
# Send email alert here
}
Start-Sleep -Seconds 60
}
# Bulk create DNS records
$records = Import-Csv "dns_records.csv" # Columns: Name, IP
foreach ($record in $records) {
Add-DnsServerResourceRecordA -ZoneName "company.com" `
-Name $record.Name -IPv4Address $record.IP
Write-Host "Created: $($record.Name).company.com -> $($record.IP)"
}
📚 Advanced PowerShell & Azure
- PowerShell for Azure Administration — €14.90 — Manage cloud infrastructure with PS
- Exchange Online Management with PowerShell — €11.90 — Automate email administration
- Bash vs PowerShell: Cross-Platform Scripting — €21.90 — Best of both worlds
- Hands-On Azure PowerShell Lab Workbook — €8.90 — Practice with real lab exercises
Conclusion
PowerShell transforms Windows Server administration from a manual, GUI-heavy process into an efficient, scriptable, and repeatable workflow. The commands in this guide represent the core toolkit every Windows administrator needs. Start with the basics, build scripts for your most repetitive tasks, and gradually automate more of your infrastructure management.
Whether you manage 5 servers or 500, PowerShell is the key to doing it efficiently and reliably.