dist/temp/WindowsUpdateTools/Private/Get-WUSystemHealth.ps1
|
function Test-WUSystemHealth { <# .SYNOPSIS Performs quick Windows Update system health assessment. .DESCRIPTION Lightweight health check focusing on common Windows Update issues that require remediation. Used to determine if remediation is needed when no specific issues are detected. .PARAMETER LogPath Path to the log file for detailed logging. .EXAMPLE $health = Test-WUSystemHealth -LogPath "C:\Logs\wu.log" .NOTES This is a private function used internally by the WindowsUpdateTools module. Returns boolean health status and specific issue indicators. #> [CmdletBinding()] param( [string]$LogPath ) Write-WULog -Message "Performing Windows Update system health assessment" -LogPath $LogPath # Initialize health result $healthResult = [PSCustomObject]@{ Healthy = $true ComponentStoreCorruption = $false ServiceIssues = $false DiskSpaceIssues = $false RecentErrors = $false ConfigurationIssues = $false Issues = @() Summary = "" } try { # Quick service check Write-WULog -Message "Checking critical Windows Update services..." -LogPath $LogPath $criticalServices = @('wuauserv', 'BITS', 'cryptsvc') foreach ($serviceName in $criticalServices) { try { $service = Get-Service -Name $serviceName -ErrorAction Stop if ($service.Status -ne 'Running') { $healthResult.ServiceIssues = $true $healthResult.Healthy = $false $healthResult.Issues += "Critical service '$serviceName' is not running" Write-WULog -Message "Service issue detected: $serviceName is $($service.Status)" -Level Warning -LogPath $LogPath } } catch { $healthResult.ServiceIssues = $true $healthResult.Healthy = $false $healthResult.Issues += "Critical service '$serviceName' is not accessible" Write-WULog -Message "Service access issue: $serviceName - $($_.Exception.Message)" -Level Warning -LogPath $LogPath } } # Quick disk space check Write-WULog -Message "Checking system disk space..." -LogPath $LogPath try { $systemDrive = Get-CimInstance -ClassName Win32_LogicalDisk | Where-Object { $_.DeviceID -eq $env:SystemDrive } $freeSpaceGB = [math]::Round($systemDrive.FreeSpace / 1GB, 2) if ($freeSpaceGB -lt 5) { $healthResult.DiskSpaceIssues = $true $healthResult.Healthy = $false $healthResult.Issues += "Critical disk space - only $freeSpaceGB GB free" Write-WULog -Message "Critical disk space issue: $freeSpaceGB GB free" -Level Warning -LogPath $LogPath } elseif ($freeSpaceGB -lt 10) { $healthResult.DiskSpaceIssues = $true $healthResult.Issues += "Low disk space - $freeSpaceGB GB free" Write-WULog -Message "Low disk space warning: $freeSpaceGB GB free" -Level Warning -LogPath $LogPath } } catch { Write-WULog -Message "Could not check disk space: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } # Quick component store health check Write-WULog -Message "Quick component store health check..." -LogPath $LogPath try { $dismOutput = & dism.exe /online /cleanup-image /checkhealth 2>&1 $dismExitCode = $LASTEXITCODE if ($dismExitCode -ne 0 -or $dismOutput -like "*Component Store is repairable*") { $healthResult.ComponentStoreCorruption = $true $healthResult.Healthy = $false $healthResult.Issues += "Component store corruption detected" Write-WULog -Message "Component store corruption detected" -Level Warning -LogPath $LogPath } } catch { Write-WULog -Message "Could not check component store health: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } # Check for recent Windows Update errors in event log Write-WULog -Message "Checking for recent Windows Update errors..." -LogPath $LogPath try { $recentErrors = Get-WinEvent -FilterHashtable @{ LogName = 'Microsoft-Windows-WindowsUpdateClient/Operational' Level = 1..2 # Critical and Error StartTime = (Get-Date).AddDays(-3) } -MaxEvents 10 -ErrorAction SilentlyContinue if ($recentErrors -and $recentErrors.Count -gt 0) { $healthResult.RecentErrors = $true $healthResult.Issues += "Found $($recentErrors.Count) recent Windows Update errors" Write-WULog -Message "Found $($recentErrors.Count) recent Windows Update errors" -Level Warning -LogPath $LogPath # If many recent errors, consider unhealthy if ($recentErrors.Count -gt 3) { $healthResult.Healthy = $false } } } catch { # Event log access issues are not critical for health assessment Write-WULog -Message "Could not check recent Windows Update errors: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } # Quick configuration check Write-WULog -Message "Checking basic Windows Update configuration..." -LogPath $LogPath try { # Check if Windows Update service is disabled $wuServiceConfig = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\wuauserv" -ErrorAction SilentlyContinue if ($wuServiceConfig -and $wuServiceConfig.Start -eq 4) { # 4 = Disabled $healthResult.ConfigurationIssues = $true $healthResult.Healthy = $false $healthResult.Issues += "Windows Update service is disabled" Write-WULog -Message "Windows Update service is disabled at system level" -Level Warning -LogPath $LogPath } # Check if automatic updates are disabled via policy $auDisabled = Get-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "NoAutoUpdate" -ErrorAction SilentlyContinue if ($auDisabled -and $auDisabled.NoAutoUpdate -eq 1) { $healthResult.ConfigurationIssues = $true $healthResult.Issues += "Automatic updates are disabled via Group Policy" Write-WULog -Message "Automatic updates disabled via Group Policy" -Level Warning -LogPath $LogPath } } catch { Write-WULog -Message "Could not check Windows Update configuration: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } # Check for pending reboot that might be blocking updates try { $pendingReboot = Test-WUPendingReboot if ($pendingReboot) { $healthResult.Issues += "Pending reboot detected - may affect Windows Update operations" Write-WULog -Message "Pending reboot detected" -Level Warning -LogPath $LogPath } } catch { Write-WULog -Message "Could not check pending reboot status: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } # Generate summary if ($healthResult.Healthy) { $healthResult.Summary = "System appears healthy for Windows Update operations" Write-WULog -Message "System health assessment: HEALTHY" -LogPath $LogPath } else { $issueCount = $healthResult.Issues.Count $healthResult.Summary = "System health issues detected ($issueCount issues found)" Write-WULog -Message "System health assessment: ISSUES DETECTED ($issueCount issues)" -Level Warning -LogPath $LogPath } # Log specific issue areas $issueAreas = @() if ($healthResult.ServiceIssues) { $issueAreas += "Services" } if ($healthResult.ComponentStoreCorruption) { $issueAreas += "Component Store" } if ($healthResult.DiskSpaceIssues) { $issueAreas += "Disk Space" } if ($healthResult.RecentErrors) { $issueAreas += "Recent Errors" } if ($healthResult.ConfigurationIssues) { $issueAreas += "Configuration" } if ($issueAreas.Count -gt 0) { Write-WULog -Message "Issue areas identified: $($issueAreas -join ', ')" -LogPath $LogPath } if ($healthResult.Issues.Count -gt 0) { Write-WULog -Message "Specific issues found:" -LogPath $LogPath foreach ($issue in $healthResult.Issues) { Write-WULog -Message " - $issue" -LogPath $LogPath } } } catch { $healthResult.Healthy = $false $healthResult.Issues += "Error during health assessment: $($_.Exception.Message)" $healthResult.Summary = "Health assessment failed" Write-WULog -Message "Error during system health assessment: $($_.Exception.Message)" -Level Error -LogPath $LogPath } return $healthResult } |