Public/Invoke-InfraHealthCheck.ps1
|
function Invoke-InfraHealthCheck { <# .SYNOPSIS Runs a comprehensive infrastructure health check and generates an HTML dashboard. .DESCRIPTION Connects to Windows servers via CIM/WinRM and collects: - Hardware inventory (OS, CPU, RAM, disk) - Disk space with threshold alerts - Critical service status - Uptime and last reboot - Pending Windows updates - Recent critical/error event log entries Produces a color-coded HTML dashboard suitable for email delivery. .PARAMETER ComputerName One or more server names to check. If not specified, queries AD for all enabled server OS computers. .PARAMETER SearchBase AD OU to scope the server query. Only used when ComputerName is not specified. .PARAMETER DiskWarningPercent Disk usage percentage to trigger a warning. Defaults to 80. .PARAMETER DiskCriticalPercent Disk usage percentage to trigger a critical alert. Defaults to 90. .PARAMETER CriticalServices List of services to monitor. Defaults to common infrastructure services. .PARAMETER OutputPath Directory for the HTML report. Defaults to .\Reports. .PARAMETER SendEmail Send the report via email. .PARAMETER EmailTo Recipient email address(es). .PARAMETER EmailFrom Sender email address. .PARAMETER SmtpServer SMTP server for sending the report. .EXAMPLE Invoke-InfraHealthCheck -ComputerName "SERVER01","SERVER02" .EXAMPLE Invoke-InfraHealthCheck -SendEmail -EmailTo "team@contoso.com" -EmailFrom "monitoring@contoso.com" -SmtpServer "smtp.contoso.com" .EXAMPLE Invoke-InfraHealthCheck -DiskWarningPercent 75 -DiskCriticalPercent 85 .NOTES Requires: CIM/WinRM access to target servers. AD module optional (for auto-discovery). #> [CmdletBinding(DefaultParameterSetName = 'Report')] param( [Parameter()] [string[]]$ComputerName, [string]$SearchBase, [ValidateRange(1, 99)] [int]$DiskWarningPercent = 80, [ValidateRange(1, 99)] [int]$DiskCriticalPercent = 90, [string[]]$CriticalServices = @('DNS', 'NTDS', 'DFSR', 'W32Time', 'WinRM', 'Spooler'), [string]$OutputPath = '.\Reports', [Parameter(ParameterSetName = 'Email')] [switch]$SendEmail, [Parameter(ParameterSetName = 'Email', Mandatory)] [string[]]$EmailTo, [Parameter(ParameterSetName = 'Email', Mandatory)] [string]$EmailFrom, [Parameter(ParameterSetName = 'Email', Mandatory)] [string]$SmtpServer ) begin { if (-not (Test-Path $OutputPath)) { New-Item -Path $OutputPath -ItemType Directory -Force | Out-Null } # Get server list from AD if not provided if (-not $ComputerName) { $adParams = @{ Filter = "OperatingSystem -like '*Server*' -and Enabled -eq `$true" Properties = @('OperatingSystem') } if ($SearchBase) { $adParams['SearchBase'] = $SearchBase } $ComputerName = (Get-ADComputer @adParams).Name } $allResults = @{ Inventory = [System.Collections.Generic.List[PSCustomObject]]::new() DiskSpace = [System.Collections.Generic.List[PSCustomObject]]::new() Services = [System.Collections.Generic.List[PSCustomObject]]::new() Offline = [System.Collections.Generic.List[string]]::new() } } process { $total = $ComputerName.Count $current = 0 foreach ($computer in $ComputerName) { $current++ Write-Progress -Activity "Health Check" -Status "$computer ($current/$total)" -PercentComplete (($current / $total) * 100) if (-not (Test-Connection -ComputerName $computer -Count 1 -Quiet)) { $allResults.Offline.Add($computer) Write-Warning "$computer is offline" continue } # Inventory $inv = Get-ServerInventory -ComputerName $computer if ($inv) { $allResults.Inventory.Add($inv) } # Disk Space $disks = Get-DiskSpaceReport -ComputerName $computer -WarningPercent $DiskWarningPercent -CriticalPercent $DiskCriticalPercent foreach ($d in $disks) { $allResults.DiskSpace.Add($d) } # Services $svc = Get-ServiceHealthReport -ComputerName $computer -ServiceName $CriticalServices foreach ($s in $svc) { $allResults.Services.Add($s) } } Write-Progress -Activity "Health Check" -Completed # Generate HTML $timestamp = Get-Date -Format 'yyyyMMdd-HHmmss' $htmlFile = Join-Path $OutputPath "InfraHealth-$timestamp.html" $html = _New-InfraHealthHtml -Results $allResults -DiskWarning $DiskWarningPercent -DiskCritical $DiskCriticalPercent $html | Out-File -FilePath $htmlFile -Encoding UTF8 Write-Verbose "Report saved: $htmlFile" # Send email if requested if ($SendEmail) { $emailParams = @{ To = $EmailTo From = $EmailFrom Subject = "Infrastructure Health Report - $(Get-Date -Format 'yyyy-MM-dd')" Body = $html BodyAsHtml = $true SmtpServer = $SmtpServer } Send-MailMessage @emailParams Write-Verbose "Report emailed to $($EmailTo -join ', ')" } # Summary $criticalDisks = @($allResults.DiskSpace | Where-Object Status -eq 'Critical').Count $stoppedServices = @($allResults.Services | Where-Object Status -ne 'Running').Count [PSCustomObject]@{ ServersChecked = $total ServersOnline = $allResults.Inventory.Count ServersOffline = $allResults.Offline.Count CriticalDisks = $criticalDisks StoppedServices = $stoppedServices ReportPath = $htmlFile } } } |