Get-AutopatchHealth.ps1
|
<#PSScriptInfo
.VERSION 1.1.0 .GUID 2c80336a-7d9b-41c0-8eb3-a80abef2dbb8 .AUTHOR Jeff Gilbert .COMPANYNAME .COPYRIGHT .TAGS Intune .LICENSEURI .PROJECTURI .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES Version 1.0.0 3.10.26 Original published version. Version 1.1.0 3.10.26 Fixed typo in report output. #> <# .SYNOPSIS Automates Autopatch health checks and validation for Windows devices enrolled in Intune. This script performs a series of checks to determine if a device is properly configured for Autopatch, including policy source verification, WSUS configuration, registry blockers, MDM enrollment status, and recent activity indicators. .DESCRIPTION The script checks the following: - Whether the device is receiving update policies from MDM (Intune) and if it's tagged for Autopatch. - If there are any WSUS server configurations that could interfere with Autopatch. - If specific registry keys that would block Autopatch are present. - If the device is enrolled in Intune by checking for key registry paths. - The last activity date of the Intune Management Extension to assess if the device has been active recently. .EXAMPLE .\Get-AutopatchHealth.ps1 Runs the script to perform Autopatch health checks on the local device. The output will indicate the status of each check with color-coded messages for easy identification of issues. .NOTES For best results, run this script in a PowerShell terminal with administrative privileges. #> # Autopatch Local Health & Blocker Validation Script Clear-Host # ----------------------------- # ChecksStart # ----------------------------- Write-Host "=== Autopatch Quick Validation ===" -ForegroundColor Cyan # ----------------------------- # Branch&AutopatchPolicyCheck # ----------------------------- Write-Host "`n[Update Policy Source - is this an Autopatch device?]" -ForegroundColor Yellow # --- Paths (use Registry:: to avoid 32-bit WOW64 redirection issues) --- $policyStatePath = 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UpdatePolicy\PolicyState' if (-not (Test-Path $policyStatePath)) { Write-Host "PolicyState registry path not found: $policyStatePath" -ForegroundColor Yellow return } $policyState = Get-ItemProperty -Path $policyStatePath -ErrorAction SilentlyContinue # ----------------------------- # BranchReadinessLevel # ----------------------------- $brl = [string]$policyState.BranchReadinessLevel $brlLabel = switch ($brl) { 'CB' { 'Current Branch' } 'B' { 'Business (SAC)' } 'RP' { 'Release Preview' } 'WIF' { 'Windows Insider Fast' } 'WIS' { 'Windows Insider Slow' } 'WIP' { 'Windows Insider Preview' } default { $brl } # fall back to raw value } Write-Host ("BranchReadinessLevel : {0} ({1})" -f $brl, $brlLabel) # ----------------------------- # PolicySources # ----------------------------- $ps = [int]$policyState.PolicySources # Decode PolicySources bitmask $psParts = @() if (($ps -band 1) -ne 0) { $psParts += 'Group Policy' } if (($ps -band 2) -ne 0) { $psParts += 'ConfigMgr' } if (($ps -band 4) -ne 0) { $psParts += 'MDM (Intune)' } $psLabel = if ($psParts.Count -gt 0) { $psParts -join ' + ' } else { 'None / Unknown' } # Autopatch tag when MDM is present $AutopatchTag = if (($ps -band 4) -ne 0) { 'Autopatch' } else { $null } $psDisplay = if ($ps -eq 4) { "$ps (Autopatch" } else { "$ps" } if ($AutopatchTag) { Write-Host ("PolicySources : {0})" -f $psDisplay) -ForegroundColor Green } else { Write-Host ("PolicySources : {0} ({1})" -f $ps, $psLabel) -ForegroundColor Red } # ----------------------------- # WSUSConfigurationCheck # ----------------------------- Write-Host "`n[WSUS Configuration - is this device looking for a WSUS server?]" -ForegroundColor Yellow $wuPolicyPath = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate' if (Test-Path $wuPolicyPath) { $wu = Get-ItemProperty -Path $wuPolicyPath -ErrorAction Stop $wuServer = [string]$wu.WUServer $wuStatusServer = [string]$wu.WUStatusServer # Consider "blank" as: $null, empty string, or whitespace-only if ([string]::IsNullOrWhiteSpace($wuServer) -and [string]::IsNullOrWhiteSpace($wuStatusServer)) { Write-Host "WSUS server information is not configured" -ForegroundColor Green } else { If ($wu.WUServer) {write-host "WSUS VALUE FOUND: WUServer : $($wu.WUServer)" -ForegroundColor Red } If ($wu.WUStatusServer) {write-host "WSUS VALUE FOUND: WUStatusServer : $($wu.WUStatusServer)" -ForegroundColor Red } } } else { Write-Host "No WSUS policy keys found" -ForegroundColor Green } # ----------------------------- # UpdateSourceKeysCheck # ----------------------------- Write-Host "`n[Update Source Registry Check - are Autopatch update source keys set to WSUS?]" -ForegroundColor Yellow $wureg = 0 # --- Paths (use Registry:: to avoid 32-bit WOW64 redirection issues) --- $UpdateSourceKeys = @( @{ Path = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UpdatePolicy\PolicyState"; ValueName = "SetPolicyDrivenUpdateSourceForDriverUpdates"; WSUSValue = "1" }, @{ Path = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UpdatePolicy\PolicyState"; ValueName = "SetPolicyDrivenUpdateSourceForFeatureUpdates"; WSUSValue = "1" }, @{ Path = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UpdatePolicy\PolicyState"; ValueName = "SetPolicyDrivenUpdateSourceForOtherUpdates"; WSUSValue = "1" }, @{ Path = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UpdatePolicy\PolicyState"; ValueName = "SetPolicyDrivenUpdateSourceForQualityUpdates"; WSUSValue = "1" } ) ForEach ($Key in $UpdateSourceKeys){ $value = Get-ItemProperty -Path $Key.Path -Name $Key.ValueName -ErrorAction SilentlyContinue if ($null -ne $value){ if ([string]$value.$($Key.ValueName) -eq $Key.WSUSValue){ Write-Host "$($Key.ValueName) is set to 1 (WSUS)" -ForegroundColor Red ; $wureg++ }} # WSUS config registry value found } If ( $wureg -eq 0){ Write-Host "No update source key issues found" -ForegroundColor Green} # ----------------------------- # AutopatchRegistryBlockerCheck # ----------------------------- Write-Host "`n[Registry Blockers - is Autopatch being blocked?]" -ForegroundColor Yellow $blockingKey = 0 # --- Paths (use Registry:: to avoid 32-bit WOW64 redirection issues) --- $regChecks = @( 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\DoNotConnectToWindowsUpdateInternetLocations', 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\DisableWindowsUpdateAccess', 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU\NoAutoUpdate' ) foreach ($path in $regChecks) { if (Test-Path $path) { Write-Host "BLOCKING KEY FOUND: $path" -ForegroundColor Red ; $blockingKey++ } } if ($blockingKey -eq 0){ Write-Host "No Autopatch registry blockers found" -ForegroundColor Green } # ----------------------------- # MDMEnrollmentCheck # ----------------------------- Write-Host "`n[Intune Enrollment - is MDM present?]" -ForegroundColor Yellow # --- Paths (use Registry:: to avoid 32-bit WOW64 redirection issues) --- $missingKey = 0 $paths = @( 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\IntuneManagementExtension', 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PolicyManager\current\device' ) foreach ($p in $paths) { if (!(Test-Path $p)){ Write-Host "Enrollment key $p NOT is present" -ForegroundColor Red ; $missingKey++} } If ($missingKey -eq 0){ Write-Host "Intune enrollment indicators are present" -ForegroundColor Green } # ----------------------------- # IMEActivityCheck # ----------------------------- Write-Host "`n[Device Activity - has the device been active within the last 30 days?]" -ForegroundColor Yellow $latestImeLog = Get-ChildItem 'C:\ProgramData\Microsoft\IntuneManagementExtension\Logs' ` -Filter '*.log' -ErrorAction SilentlyContinue | Sort-Object LastWriteTime -Descending | Select-Object -First 1 if ($latestImeLog) { $lastActivity = $latestImeLog.LastWriteTime $cutoffDate = (Get-Date).AddDays(-30) Write-Host "Last Intune activity (IME): $lastActivity" if ($lastActivity -ge $cutoffDate) { Write-Host "Status: ACTIVE (within last 30 days)" -ForegroundColor Green } else { Write-Host "Status: STALE (older than 30 days)" -ForegroundColor Yellow } } else { Write-Host "No Intune Management Extension logs found." -ForegroundColor Red } # ----------------------------- # ChecksComplete # ----------------------------- Write-Host "`nValidation complete."`n -ForegroundColor Cyan Exit |