**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.