**Server Health Check and Update Wrapper** In this blog post, we will be exploring a PowerShell script that checks the health of Windows servers in an Active Directory domain. The script performs several key functions: it filters out excluded servers, checks connectivity, checks disk space, and prepares for Windows updates. **Prerequisites** Before we dive into the script itself, let's take a look at what you'll need to run this script: * PowerShell 5.1 or higher * Active Directory Domain Services (AD DS) * Remote Server Administration Tools (RSAT) installed on your machine **The Script** Here is the full code for the script: ```
Configuration
$LogPath = "$PSScriptRoot\logs"
$ExcludedFile = "$PSScriptRoot\Excluded-servers.txt"
$MinFreeSpaceGB = 10
$LogDate = Get-Date -Format "ddMMyyyy"
$LogFile = "$LogPath\Update-log-$LogDate.log"
Helper Function: Logging
function Write-Log {
param (
[Parameter(Mandatory=$true)] [string]$Message,
[string]$Color = "White",
[switch]$NoConsole
)
$TimeStamp = Get-Date -Format "HH:mm:ss dd/MM/yyyy"
$LogLine = "$TimeStamp : $Message"
# Write to file
Add-Content -Path $LogFile -Value $LogLine -ErrorAction SilentlyContinue
# Write to console (optional)
if (-not $NoConsole) {
Write-Host $Message -ForegroundColor $Color
}
}
Initialization
Clear-Host
# Ensure Log Directory Exists
if (!(Test-Path $LogPath)) {
New-Item -Path $LogPath -ItemType Directory -Force | Out-Null
}
# Create Log File
if (!(Test-Path $LogFile)) {
New-Item -Path $LogFile -ItemType File -Force | Out-Null
Write-Log -Message "Logfile Created" -Color Cyan
}
# Check/Create Exclusion File
$ExcludedList = @()
if (Test-Path $ExcludedFile) {
$ExcludedList = Get-Content $ExcludedFile
Write-Log -Message "Excluded Servers file found. $($ExcludedList.Count) servers excluded." -Color Cyan
} else {
New-Item -Path $ExcludedFile -ItemType File -Force | Out-Null
Write-Log -Message "Excluded Servers file not found, created empty file." -Color Yellow
}
Main Logic
# 1. Get Domain Info
try {
$Domain = (Get-ADDomain).DNSRoot
Write-Log -Message "Domain detected: $Domain" -Color Green
}
catch {
Write-Log -Message "Error: Unable to contact Active Directory. Ensure RSAT is installed." -Color Red
Break
}
# 2. Get Servers (Optimized Query)
Write-Log -Message "Querying Active Directory for Windows Servers..." -Color Cyan
$AllServers = Get-ADComputer -Filter {OperatingSystem -like "*windows*server*"} | Select-Object -ExpandProperty Name | Sort-Object
# 3. Filter Exclusions
$TargetServers = $AllServers | Where-Object { $_ -notin $ExcludedList }
$SkippedCount = ($AllServers.Count - $TargetServers.Count)
Write-Log -Message "Found $($AllServers.Count) total servers. Processing $($TargetServers.Count). ($SkippedCount excluded)" -Color Cyan
# 4. Check Connectivity (Parallel)
Write-Log -Message "Checking connectivity..." -Color Cyan
$OnlineServers = @()
$OfflineServers = @()
# Test-Connection in parallel usually requires WMI/ICMP.
# A quick way to do this in bulk is actually using Test-Connection with -ComputerName taking an array (PS5.1+)
$TestResults = Test-Connection -ComputerName $TargetServers -Count 1 -ErrorAction SilentlyContinue -AsJob | Receive-Job -Wait
foreach ($Server in $TargetServers) {
if ($TestResults | Where-Object { $_.Address -eq $Server -and $_.StatusCode -eq 0 }) {
$OnlineServers += $Server
} else {
$OfflineServers += $Server
Write-Log -Message "$Server is OFFLINE or blocking ICMP" -Color DarkGray
}
}
# 5. Check Disk Space & Updates (Parallel Execution using Invoke-Command)
if ($OnlineServers.Count -gt 0) {
Write-Log -Message "Scanning $($OnlineServers.Count) online servers for disk space..." -Color Green
# Run the check on all servers simultaneously
$Results = Invoke-Command -ComputerName $OnlineServers -ErrorAction SilentlyContinue -ScriptBlock {
$SystemDrive = Get-PSDrive C | Select-Object Used, Free
$FreeGB = [math]::Round($SystemDrive.Free / 1GB, 2)
# Create a custom object to return to the host
[PSCustomObject]@{
ServerName = $env:COMPUTERNAME
FreeGB = $FreeGB
}
# --- UPDATE SECTION (Still Commented, but improved) ---
<#
# Check if module exists, if not try to install (requires internet)
if (-not (Get-Module -ListAvailable -Name PSWindowsUpdate)) {
Install-Module -Name PSWindowsUpdate -Force -Confirm:$false
}
Import-Module PSWindowsUpdate
Get-WindowsUpdate -AcceptAll -Install -Verbose
#>
}
# 6. Process Results
foreach ($Res in $Results) {
if ($Res.FreeGB -lt $MinFreeSpaceGB) {
Write-Log -Message "WARNING: $($Res.ServerName) has low disk space: $($Res.FreeGB) GB" -Color Magenta
} else {
Write-Log -Message "$($Res.ServerName) OK. Free Space: $($Res.FreeGB) GB" -Color Green
}
}
}
Write-Log -Message "Finished processing server list." -Color Cyan
**How it Works** This script starts by setting up some variables for logging and excluding certain servers from the scan. It then uses the `Get-ADComputer` cmdlet to query Active Directory for all Windows servers. Next, it filters out any excluded servers and sorts the remaining list of servers. Then, it checks connectivity for each server using the `Test-Connection` cmdlet in parallel. After that, it checks disk space on each online server using the `Get-PSDrive` cmdlet. Finally, it processes the results and logs any warnings or errors. **Conclusion** In this blog post, we explored a PowerShell script that checks the health of Windows servers in an Active Directory domain. The script filters out excluded servers, checks connectivity, checks disk space, and prepares for Windows updates. With this script, you can easily monitor and maintain your server fleet.