PowerShell is the command-line backbone of modern Windows Server administration. Whether you are managing one server or a hundred, scripting repetitive tasks saves hours and eliminates human error. These ten scripts cover the tasks every Windows admin faces weekly — learn them, adapt them, and build your own library from here.
1. Get a System Inventory Report
Quickly document a server's hardware and OS details — useful for asset management and troubleshooting:
$info = Get-ComputerInfo
[PSCustomObject]@{
Hostname = $env:COMPUTERNAME
OS = $info.OsName
Version = $info.OsVersion
RAM_GB = [math]::Round($info.CsTotalPhysicalMemory / 1GB, 2)
CPU = $info.CsProcessors.Name
LastBoot = $info.OsLastBootUpTime
} | Format-List
2. Bulk Create Active Directory Users from CSV
Prepare a CSV with columns: FirstName, LastName, Department, OU. Then run:
Import-Csv "C:Temp
ew-users.csv" | ForEach-Object {
$username = ($_.FirstName[0] + $_.LastName).ToLower()
$upn = "$username@corp.local"
New-ADUser `
-Name "$($_.FirstName) $($_.LastName)" `
-GivenName $_.FirstName `
-Surname $_.LastName `
-SamAccountName $username `
-UserPrincipalName $upn `
-Path "OU=$($_.Department),OU=Users,DC=corp,DC=local" `
-AccountPassword (ConvertTo-SecureString "Welcome1!" -AsPlainText -Force) `
-ChangePasswordAtLogon $true `
-Enabled $true
Write-Host "Created: $upn"
}
3. Find All Inactive User Accounts
Stale accounts are a security risk. Find users who have not logged in for 90 days:
$cutoff = (Get-Date).AddDays(-90)
Get-ADUser -Filter {LastLogonDate -lt $cutoff -and Enabled -eq $true} `
-Properties LastLogonDate, Department |
Select-Object Name, SamAccountName, Department, LastLogonDate |
Sort-Object LastLogonDate |
Export-Csv "C:Tempinactive-users.csv" -NoTypeInformation
4. Monitor Disk Space Across Multiple Servers
$servers = "srv-dc01", "srv-web01", "srv-files01"
$servers | ForEach-Object {
Get-WmiObject Win32_LogicalDisk -ComputerName $_ -Filter "DriveType=3" |
Select-Object `
@{N="Server";E={$_.__SERVER}},
DeviceID,
@{N="Size_GB";E={[math]::Round($_.Size/1GB,1)}},
@{N="Free_GB";E={[math]::Round($_.FreeSpace/1GB,1)}},
@{N="Used_%";E={[math]::Round((($_.Size - $_.FreeSpace)/$_.Size)*100,1)}}
} | Format-Table -AutoSize
5. Restart a Service and Verify It Comes Back Up
$serviceName = "Spooler"
$server = "srv-print01"
Restart-Service -Name $serviceName -ComputerName $server
Start-Sleep -Seconds 5
$status = (Get-Service -Name $serviceName -ComputerName $server).Status
if ($status -eq "Running") {
Write-Host "$serviceName on $server is Running." -ForegroundColor Green
} else {
Write-Warning "$serviceName on $server is $status — investigate immediately."
}
6. Export All Members of a Security Group
$groupName = "Finance-ReadOnly"
Get-ADGroupMember -Identity $groupName -Recursive |
Get-ADUser -Properties DisplayName, EmailAddress, Department |
Select-Object DisplayName, SamAccountName, EmailAddress, Department |
Export-Csv "C:Temp$groupName-members.csv" -NoTypeInformation
7. Check Windows Update Status
$session = New-Object -ComObject Microsoft.Update.Session
$searcher = $session.CreateUpdateSearcher()
$results = $searcher.Search("IsInstalled=0 and Type='Software'")
Write-Host "Pending updates: $($results.Updates.Count)"
$results.Updates | Select-Object Title, MsrcSeverity | Format-Table -AutoSize
8. Find and Kill Processes Consuming High CPU
Get-Process | Sort-Object CPU -Descending | Select-Object -First 10 Name, Id, CPU, WorkingSet |
ForEach-Object {
$_ | Add-Member -NotePropertyName RAM_MB -NotePropertyValue ([math]::Round($_.WorkingSet/1MB,1)) -PassThru
} | Select-Object Name, Id, CPU, RAM_MB | Format-Table -AutoSize
9. Create a Local Admin Account on Remote Servers
$servers = "srv-web01","srv-app01"
$password = Read-Host "Enter password" -AsSecureString
foreach ($srv in $servers) {
Invoke-Command -ComputerName $srv -ScriptBlock {
param($pw)
New-LocalUser -Name "svc-admin" -Password $pw -FullName "Local Admin" -Description "Break-glass account" -PasswordNeverExpires $true
Add-LocalGroupMember -Group "Administrators" -Member "svc-admin"
} -ArgumentList $password
Write-Host "Account created on $srv"
}
10. Generate an HTML Server Health Report
$report = @"
Server Health: $env:COMPUTERNAME
Generated: $(Get-Date)
Top 5 Processes by CPU
$(Get-Process | Sort-Object CPU -Descending | Select-Object -First 5 Name, CPU | ConvertTo-Html -Fragment)
Disk Space
$(Get-PSDrive -PSProvider FileSystem | Select-Object Name, Used, Free | ConvertTo-Html -Fragment)
"@
$report | Out-File "C:Temphealth-report.html"
Invoke-Item "C:Temphealth-report.html"
Save your scripts in a structured folder like C:Scripts and version-control them with Git. A personal script library is one of the most valuable assets a Windows admin can build over their career.
Running PowerShell Scripts: Execution Policy Explained
By default, Windows blocks all PowerShell scripts from running — a policy intended to prevent accidental execution of downloaded scripts. Before you can run your first .ps1 file, you need to understand and set the appropriate execution policy.
The most commonly used policies are: Restricted (default — no scripts at all), RemoteSigned (local scripts run freely; scripts downloaded from the internet must be digitally signed by a trusted publisher), and Unrestricted (all scripts run, but downloaded scripts trigger a confirmation prompt). For server administration work, RemoteSigned is the standard production setting — it is permissive enough to run your own scripts while blocking untrusted downloaded ones.
# View the current policy
Get-ExecutionPolicy
# Set to RemoteSigned for the local machine (requires Administrator)
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine
# Run a one-off script bypassing policy (without permanently changing it)
powershell.exe -ExecutionPolicy Bypass -File .\myscript.ps1
Always set execution policy intentionally and document why, especially on servers. Avoid Unrestricted in production; RemoteSigned provides a practical balance of usability and security.
Frequently Asked Questions
- What is the difference between PowerShell 5.1 and PowerShell 7?
Windows PowerShell 5.1 ships built into Windows and will not receive new features — it is maintained for compatibility only. PowerShell 7 is the actively developed, cross-platform successor built on .NET Core. It runs on Windows, Linux, and macOS, supports newer language features, and has better performance. For new scripts, target PowerShell 7; for Windows-only management that depends on legacy WMI or COM modules that only work in 5.1, stick with the built-in version. Both can coexist on the same machine. - How do I connect to a remote Windows Server with PowerShell?
Use PowerShell Remoting, which runs over WS-Management (WinRM). Enable it on the target server withEnable-PSRemoting -Forcefrom an elevated prompt. Then from your workstation:Enter-PSSession -ComputerName ServerName -Credential (Get-Credential)for an interactive session, orInvoke-Command -ComputerName ServerName -ScriptBlock { Get-Service }to run a command remotely. Ensure WinRM is allowed through the Windows Firewall and that the target server is either in the same domain or added to the local TrustedHosts list. - How do I schedule a PowerShell script to run automatically?
Use Windows Task Scheduler. The action should be: Program =powershell.exe, Arguments =-ExecutionPolicy Bypass -NonInteractive -File "C:\Scripts\myscript.ps1". The-NonInteractiveflag prevents any prompts that would hang the task. Run the task as a dedicated service account with the minimum required permissions rather than as your personal account or SYSTEM. Test by right-clicking the task and selecting "Run" to confirm it works in the scheduler's context before relying on automatic triggers. - What does
$_mean in PowerShell?$_is the automatic variable representing the current object in the pipeline. When you pipe objects throughWhere-Object,ForEach-Object, orSelect-Object,$_refers to the object currently being processed. For example,Get-Process | Where-Object { $_.CPU -gt 10 }filters to processes where the CPU property exceeds 10. You can also write the more readable alias$PSItemin newer scripts. Understanding$_is fundamental to writing effective PowerShell pipelines.