Windows Scripts

Useful local Windows and Active Directory admin scripts with the same card layout. For Exchange Online and Entra/M365 scripts, use Cloud Scripts.

Windows Health Snapshot
Collect uptime, CPU/memory, disk, and top process usage in one report.
Local Health Built-in
Built-in
# Run in elevated PowerShell
$os = Get-CimInstance Win32_OperatingSystem
$uptime = (Get-Date) - $os.LastBootUpTime

Write-Host "=== System ==="
Get-ComputerInfo | Select-Object WindowsProductName, WindowsVersion, CsName

Write-Host "`n=== Uptime ==="
"{0} days {1} hours" -f $uptime.Days, $uptime.Hours

Write-Host "`n=== Memory ==="
Get-CimInstance Win32_OperatingSystem |
  Select-Object @{N='FreeGB';E={[math]::Round($_.FreePhysicalMemory/1MB,2)}},
                @{N='TotalGB';E={[math]::Round($_.TotalVisibleMemorySize/1MB,2)}}

Write-Host "`n=== Disk ==="
Get-Volume | Select-Object DriveLetter, FileSystemLabel, FileSystem,
  @{N='SizeGB';E={[math]::Round($_.Size/1GB,2)}},
  @{N='FreeGB';E={[math]::Round($_.SizeRemaining/1GB,2)}}
Pending Reboot Check
Checks registry markers commonly used to flag pending reboot state.
Maintenance Built-in
Built-in
# Run in elevated PowerShell
$paths = @(
  'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending',
  'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired',
  'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager'
)

$pending = $false
foreach ($path in $paths) {
  if (Test-Path $path) { $pending = $true }
}

if ($pending) {
  Write-Host 'Pending reboot detected.' -ForegroundColor Yellow
} else {
  Write-Host 'No pending reboot detected.' -ForegroundColor Green
}
Recent Critical/Error Events
Pulls recent System/Application critical and error events for triage.
Diagnostics Built-in
Built-in
# Run in elevated PowerShell
Look-back (hours)
$Hours = ##HOURS##
$start = (Get-Date).AddHours(-$Hours)

Get-WinEvent -FilterHashtable @{
  LogName = @('System', 'Application')
  Level   = 1,2
  StartTime = $start
} -ErrorAction SilentlyContinue |
Select-Object TimeCreated, LogName, Id, LevelDisplayName, ProviderName, Message |
Sort-Object TimeCreated -Descending |
Select-Object -First 120
Restart Service + Validate
Restarts a service, waits briefly, then verifies status.
Services Built-in
Built-in
# Run in elevated PowerShell
Service name
$ServiceName = '##SERVICE_NAME##'

Restart-Service -Name $ServiceName -Force
Start-Sleep -Seconds 3

Get-Service -Name $ServiceName |
  Select-Object Name, Status, StartType, DisplayName
Get Local Disk Free Space
Shows local fixed drives with total size, free space, and free percentage.
Local Health Built-in
Built-in
# Run in an elevated PowerShell session on the target machine
Get-CimInstance Win32_LogicalDisk -Filter "DriveType=3" |
    Select-Object DeviceID,
        @{N="Size (GB)"; E={[math]::Round($_.Size / 1GB, 2)}},
        @{N="Free (GB)"; E={[math]::Round($_.FreeSpace / 1GB, 2)}},
        @{N="Free %"; E={[math]::Round(($_.FreeSpace / $_.Size) * 100, 1)}} |
    Sort-Object "Free %" |
    Format-Table -AutoSize
Get Local Administrators Group Members
Lists all members of the local Administrators group for privilege auditing.
Local Health Built-in
Built-in
# Run in an elevated PowerShell session on the target machine
Get-LocalGroupMember -Group "Administrators" |
    Select-Object Name, ObjectClass, PrincipalSource |
    Sort-Object Name |
    Format-Table -AutoSize
Get Top CPU Processes (Live Sample)
Samples process CPU usage over a short interval and returns top CPU consumers.
Local Health Built-in
Built-in
# Run in PowerShell on the target machine
Sample duration (seconds)
$sampleSeconds = ##SECONDS##

$before = Get-Process | Select-Object Id, ProcessName, CPU
Start-Sleep -Seconds $sampleSeconds
$after = Get-Process | Select-Object Id, ProcessName, CPU

$report = foreach ($p in $after) {
    $old = $before | Where-Object { $_.Id -eq $p.Id }
    if ($old -and $p.CPU -ne $null -and $old.CPU -ne $null) {
        [PSCustomObject]@{
            ProcessName = $p.ProcessName
            Id          = $p.Id
            CpuSeconds  = [math]::Round(($p.CPU - $old.CPU), 2)
        }
    }
}

$report | Sort-Object CpuSeconds -Descending | Select-Object -First 15 | Format-Table -AutoSize
Get Automatic Services Not Running
Finds services set to Automatic startup that are currently stopped.
Services Built-in
Built-in
# Run in PowerShell on the target machine
Get-Service |
    Where-Object { $_.StartType -eq "Automatic" -and $_.Status -ne "Running" } |
    Select-Object Name, DisplayName, Status, StartType |
    Sort-Object DisplayName |
    Format-Table -AutoSize
Get Locked Out AD Accounts
Finds all currently locked-out Active Directory accounts with the lockout time and source DC.
Active Directory ActiveDirectory
ActiveDirectory
# Run on a Domain Controller or machine with RSAT installed
Search-ADAccount -LockedOut |
    Get-ADUser -Properties LockedOut, BadLogonCount, BadPasswordTime, LastBadPasswordAttempt |
    Select-Object Name, SamAccountName, LockedOut, BadLogonCount, LastBadPasswordAttempt |
    Format-Table -AutoSize
Unlock AD Account
Unlocks a locked Active Directory user account.
Active Directory ActiveDirectory
ActiveDirectory
# Run on a Domain Controller or machine with RSAT installed
SAM account name
$samAccount = "##SAM_ACCOUNT##"

Unlock-ADAccount -Identity $samAccount
Write-Host "Unlocked account: $samAccount" -ForegroundColor Green

# Verify
Get-ADUser -Identity $samAccount -Properties LockedOut, BadLogonCount |
    Select-Object Name, SamAccountName, LockedOut, BadLogonCount
Find Inactive AD Users
Lists enabled AD user accounts that have not logged on within a specified number of days.
Active Directory ActiveDirectory
ActiveDirectory
# Run on a Domain Controller or machine with RSAT installed
Days of inactivity
$inactiveDays = ##DAYS##
$cutoff = (Get-Date).AddDays(-$inactiveDays)

Get-ADUser -Filter { Enabled -eq $true } -Properties LastLogonDate, Description |
    Where-Object { $_.LastLogonDate -lt $cutoff -or $_.LastLogonDate -eq $null } |
    Select-Object Name, SamAccountName, LastLogonDate, Description |
    Sort-Object LastLogonDate |
    Format-Table -AutoSize
Get AD Group Members
Lists all members of a specified Active Directory group, including nested group resolution.
Active Directory ActiveDirectory
ActiveDirectory
# Run on a Domain Controller or machine with RSAT installed
Group name
$groupName = "##GROUP_NAME##"

# Direct members
Write-Host "Direct members of: $groupName" -ForegroundColor Cyan
Get-ADGroupMember -Identity $groupName | Get-ADUser -Properties EmailAddress |
    Select-Object Name, SamAccountName, EmailAddress | Format-Table -AutoSize

# All members including nested
Write-Host "`nAll members (including nested groups):" -ForegroundColor Cyan
Get-ADGroupMember -Identity $groupName -Recursive | Get-ADUser -Properties EmailAddress |
    Select-Object Name, SamAccountName, EmailAddress | Format-Table -AutoSize
Reset AD Password & Force Change
Resets an Active Directory user password and forces them to change it at next logon.
Active Directory ActiveDirectory
ActiveDirectory
# Run on a Domain Controller or machine with RSAT installed
SAM account name
Temporary password
$samAccount = "##SAM_ACCOUNT##"
$newPassword = ConvertTo-SecureString "##TEMP_PASSWORD##" -AsPlainText -Force

Set-ADAccountPassword -Identity $samAccount -NewPassword $newPassword -Reset
Set-ADUser -Identity $samAccount -ChangePasswordAtLogon $true

Write-Host "Password reset for: $samAccount" -ForegroundColor Green
Write-Host "User must change password at next logon." -ForegroundColor Yellow
Get Recently Created AD Accounts
Lists AD user accounts created within the last N days. Useful for onboarding audits.
Active Directory ActiveDirectory
ActiveDirectory
# Run on a Domain Controller or machine with RSAT installed
Created in last N days
$days = ##DAYS##
$cutoff = (Get-Date).AddDays(-$days)

Get-ADUser -Filter { WhenCreated -ge $cutoff } -Properties WhenCreated, EmailAddress, Description |
    Select-Object Name, SamAccountName, WhenCreated, EmailAddress, Description |
    Sort-Object WhenCreated -Descending |
    Format-Table -AutoSize
Defender Quick Scan + Threat Status
Starts a quick Defender scan and checks threat state.
Security Defender
Defender
# Run in elevated PowerShell
Start-MpScan -ScanType QuickScan

Get-MpComputerStatus |
  Select-Object AMRunningMode, AntivirusEnabled, RealTimeProtectionEnabled,
                QuickScanStartTime, QuickScanEndTime,
                AntivirusSignatureLastUpdated
Local Administrators Group Audit
Lists all members of local Administrators group.
Security Built-in
Built-in
# Run in elevated PowerShell
Get-LocalGroupMember -Group 'Administrators' |
  Select-Object Name, ObjectClass, PrincipalSource
Firewall Profile Baseline Check
Shows current firewall profile states and default actions.
Security NetSecurity
NetSecurity
# Run in elevated PowerShell
Get-NetFirewallProfile |
  Select-Object Name, Enabled, DefaultInboundAction, DefaultOutboundAction,
                NotifyOnListen, AllowInboundRules, AllowLocalFirewallRules
DNS Flush + Resolve Test
Flushes local DNS cache and tests name resolution.
Network Built-in
Built-in
# Run in elevated PowerShell for cache flush
Hostname to test
$HostToTest = '##HOST_TO_TEST##'

ipconfig /flushdns | Out-Null
Resolve-DnsName -Name $HostToTest -Type A
Resolve-DnsName -Name $HostToTest -Type AAAA -ErrorAction SilentlyContinue
TCP Port Smoke Test
Checks multiple ports against a target host.
Network Built-in
Built-in
# Standard PowerShell session
Target host
Ports (comma-separated)
$Target = '##TARGET##'
$Ports = '##PORTS##' -split ',' | ForEach-Object { $_.Trim() }

foreach ($p in $Ports) {
  $result = Test-NetConnection -ComputerName $Target -Port ([int]$p) -WarningAction SilentlyContinue
  [PSCustomObject]@{
    Host = $Target
    Port = $p
    TcpTestSucceeded = $result.TcpTestSucceeded
  }
}
Installed Updates Report
Exports installed hotfixes from the last N days.
Maintenance Built-in
Built-in
# Standard PowerShell session
Look-back (days)
$Days = ##DAYS##
$Cutoff = (Get-Date).AddDays(-$Days)

Get-HotFix |
  Where-Object { $_.InstalledOn -ge $Cutoff } |
  Sort-Object InstalledOn -Descending |
  Select-Object HotFixID, Description, InstalledBy, InstalledOn
Temp Folder Cleanup
Cleans machine and user temp directories older than N days.
Maintenance Built-in
Built-in
# Run in elevated PowerShell
Delete older than (days)
$Days = ##DAYS##
$paths = @(
  "$env:WINDIR\Temp",
  "$env:TEMP"
)

$cutoff = (Get-Date).AddDays(-$Days)
foreach ($p in $paths) {
  if (Test-Path $p) {
    Get-ChildItem -Path $p -Recurse -Force -ErrorAction SilentlyContinue |
      Where-Object { -not $_.PSIsContainer -and $_.LastWriteTime -lt $cutoff } |
      Remove-Item -Force -ErrorAction SilentlyContinue
  }
}
Write-Host "Cleanup complete"
No scripts match your search.

Frequently asked questions

Do these scripts require admin rights?
Many do. Run PowerShell as Administrator for service control, security, firewall, and event log commands.
Can I edit values before copy/download?
Yes. Expand any script card, change variable fields, then copy or download the rendered script.
Where are cloud tenant scripts?
Exchange and M365/Entra tenant scripts are in Cloud Scripts. Windows Scripts includes local endpoint/server and Active Directory tasks.