← Back to articles PowerShell

Diagnosing and Remediating Windows Autopatch Policy Alerts

Diagnosing and Remediating Windows Autopatch Policy Alerts

Windows Autopatch simplifies update management across your organization, but misconfigured device policies can silently block updates and trigger critical alerts in the Intune management portal. This article explores the two most common Autopatch policy failures—disabled automatic updates and excluded driver updates—and provides a production-ready PowerShell script to identify, report, and remediate affected devices at scale.

Critical Context These alerts represent genuine service delivery failures. Devices with AllowAutoUpdate set to 0 or 5, or with ExcludeWUDriversInQualityUpdate set to 1, will not receive updates through Autopatch even if they appear "Ready" in the portal. The script below helps you find and fix these before they compound into patch compliance issues.

What This Script Does

This PowerShell utility connects to Microsoft Graph, queries all Intune-managed devices, and identifies those with policy misconfigurations that block Windows Autopatch from delivering updates. It returns two critical datasets: devices with automatic update policies set to notify-only or disabled (AllowAutoUpdate ∈ {0, 5}), and devices with driver updates explicitly excluded from quality updates (ExcludeWUDriversInQualityUpdate = 1). The script outputs a detailed CSV report suitable for handoff to remediation teams, including device names, users, policy values, and recommended actions. Use this weekly as part of your Autopatch health monitoring routine, or on-demand when the Intune portal surfaces Autopatch alerts.

Prerequisites:

  • PowerShell 7.0 or later (Windows PowerShell 5.1 supported but untested)
  • Microsoft Graph PowerShell SDK: Install-Module Microsoft.Graph -Scope CurrentUser
  • Graph API scopes: DeviceManagementConfiguration.Read.All, Device.Read.All
  • Intune administrator or Device Manager role in Azure AD
  • Network access to graph.microsoft.com (no proxy auth required for interactive login)

The Complete Script

# =============================================================================
# Windows Autopatch Policy Alert Analyzer
# Author: Souhaiel MORHAG | msendpoint.com
# License: MIT
# Version: 1.0
# Description: Identify devices with Autopatch-blocking policy misconfigurations
# =============================================================================

[CmdletBinding()]
param(
    [Parameter(Mandatory = $false)]
    [string]$OutputPath = "$([System.Environment]::GetFolderPath('Desktop'))/autopatch-policy-report-$(Get-Date -Format 'yyyyMMdd-HHmmss').csv",
    
    [Parameter(Mandatory = $false)]
    [switch]$IncludeCompliant,
    
    [Parameter(Mandatory = $false)]
    [int]$ThrottleLimit = 5
)

begin {
    Write-Host "[*] Windows Autopatch Policy Alert Analyzer v1.0" -ForegroundColor Cyan
    Write-Host "[*] Output will be saved to: $OutputPath" -ForegroundColor Gray
    
    # Authenticate to Microsoft Graph
    try {
        Write-Host "[*] Authenticating to Microsoft Graph..." -ForegroundColor Cyan
        Connect-MgGraph -Scopes "DeviceManagementConfiguration.Read.All", "Device.Read.All" -NoWelcome -ErrorAction Stop
        Write-Host "[+] Authentication successful" -ForegroundColor Green
    } catch {
        Write-Error "Failed to authenticate: $_"
        exit 1
    }
    
    $results = @()
    $deviceCount = 0
    $nonCompliantCount = 0
}

process {
    try {
        # Get all Intune-managed devices
        Write-Host "[*] Querying Intune-managed devices..." -ForegroundColor Cyan
        $devices = Get-MgDeviceManagementManagedDevice -All -Property "id,displayName,userPrincipalName,complianceState,osVersion,lastSyncDateTime" -ErrorAction Stop
        
        Write-Host "[+] Found $($devices.Count) managed devices" -ForegroundColor Green
        
        # Process each device for policy violations
        $devices | ForEach-Object -Parallel {
            $device = $_
            $deviceInfo = @{
                DeviceId = $device.Id
                DeviceName = $device.DisplayName
                UserPrincipalName = $device.UserPrincipalName
                LastSync = $device.LastSyncDateTime
                OSVersion = $device.OsVersion
                AllowAutoUpdatePolicy = "Unknown"
                ExcludeDriversPolicy = "Unknown"
                Alert = @()
            }
            
            try {
                # Query device configuration for AllowAutoUpdate policy (WindowsUpdate CSP)
                $deviceConfigs = Get-MgDeviceManagementDeviceConfiguration -Filter "deviceIds/any(d:d eq '$($device.Id)')" -ErrorAction SilentlyContinue
                
                foreach ($config in $deviceConfigs) {
                    if ($config.AdditionalProperties.allDevicesAssigned -or $config.roleScopeTagIds.Count -gt 0) {
                        # Parse the policy payload for AllowAutoUpdate
                        if ($config.AdditionalProperties.settings) {
                            $settings = $config.AdditionalProperties.settings | ConvertFrom-Json -ErrorAction SilentlyContinue
                            if ($settings.allowAutoUpdate) {
                                $deviceInfo.AllowAutoUpdatePolicy = $settings.allowAutoUpdate
                                if ($settings.allowAutoUpdate -in @(0, 5)) {
                                    $deviceInfo.Alert += "AllowAutoUpdate=$($settings.allowAutoUpdate): Updates blocked (notify-only or disabled)"
                                }
                            }
                        }
                        
                        # Parse for ExcludeWUDriversInQualityUpdate
                        if ($config.AdditionalProperties.settings) {
                            if ($settings.excludeWUDriversInQualityUpdate -eq $true -or $settings.excludeWUDriversInQualityUpdate -eq 1) {
                                $deviceInfo.ExcludeDriversPolicy = "True"
                                $deviceInfo.Alert += "ExcludeWUDriversInQualityUpdate=1: Driver updates blocked"
                            }
                        }
                    }
                }
                
                # Fallback: query compliance state and device configuration profiles
                if ($deviceInfo.AllowAutoUpdatePolicy -eq "Unknown") {
                    try {
                        $compliance = Get-MgDeviceManagementDeviceCompliancePolicy -Filter "deviceIds/any(d:d eq '$($device.Id)')" -ErrorAction SilentlyContinue
                        if ($compliance) {
                            $deviceInfo.AllowAutoUpdatePolicy = "Compliant"
                        }
                    } catch {}
                }
            } catch {
                $deviceInfo.Alert += "Error querying policies: $($_.Message)"
            }
            
            [pscustomobject]$deviceInfo
        } -ThrottleLimit $using:ThrottleLimit | ForEach-Object {
            $results += $_
            if ($_.Alert.Count -gt 0) {
                $nonCompliantCount++
            }
            $deviceCount++
        }
        
        Write-Host "[+] Policy scan complete: $nonCompliantCount non-compliant devices found" -ForegroundColor Green
        
    } catch {
        Write-Error "Failed to query devices: $_"
        exit 1
    }
}

end {
    try {
        # Filter results based on user preference
        if (-not $IncludeCompliant) {
            $results = $results | Where-Object { $_.Alert.Count -gt 0 }
        }
        
        # Export to CSV with formatted alerts
        $results | Select-Object @(
            @{ Label = "Device Name"; Expression = { $_.DeviceName } }
            @{ Label = "User"; Expression = { $_.UserPrincipalName } }
            @{ Label = "OS Version"; Expression = { $_.OSVersion } }
            @{ Label = "Last Sync"; Expression = { $_.LastSync } }
            @{ Label = "AllowAutoUpdate Policy"; Expression = { $_.AllowAutoUpdatePolicy } }
            @{ Label = "ExcludeDrivers Policy"; Expression = { $_.ExcludeDriversPolicy } }
            @{ Label = "Alerts"; Expression = { $_.Alert -join " | " } }
            @{ Label = "Device ID"; Expression = { $_.DeviceId } }
        ) | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8 -Force
        
        Write-Host "\n[+] Report exported to: $OutputPath" -ForegroundColor Green
        Write-Host "[+] Total devices scanned: $deviceCount" -ForegroundColor Green
        Write-Host "[+] Non-compliant devices: $nonCompliantCount" -ForegroundColor Yellow
        
        # Display summary table
        Write-Host "\n=== SUMMARY ===\n" -ForegroundColor Cyan
        $results | Where-Object { $_.Alert.Count -gt 0 } | Select-Object -First 10 | Format-Table -AutoSize
        
        if ($nonCompliantCount -gt 10) {
            Write-Host "... and $($nonCompliantCount - 10) more devices listed in the full report." -ForegroundColor Gray
        }
        
    } catch {
        Write-Error "Failed to export results: $_"
        exit 1
    } finally {
        Disconnect-MgGraph -ErrorAction SilentlyContinue
        Write-Host "\n[*] Graph session closed" -ForegroundColor Gray
    }
}

How It Works

Autopatch Policy Alert Detection Flow Connect-MgGraph OAuth 2.0 Interactive Login Get-MgDeviceManagement ManagedDevice ~5k devices /org Check Policies AllowAutoUpdate ExcludeDrivers Export CSV Alerts & Remediation ALERT: AllowAutoUpdate ∈ {0, 5} Policy blocks automatic updates Device shows "Ready" but receives NO patches ALERT: ExcludeWUDrivers = 1 Driver updates excluded from quality feed Autopatch cannot deploy driver patches Legend Data Flow Policy Violation
Script execution flow: authenticate → query all devices → parallel policy check → report non-compliant devices. Dashed red lines show the two critical policy failure paths.
The script works in four phases. **Authentication** uses interactive Microsoft Graph login and requests the required scopes. **Enumeration** fetches all Intune-managed devices with their display names, user assignments, and sync timestamps. **Policy Analysis** (the heavy lifting) runs in parallel across devices—each thread queries the device's assigned configuration policies looking for two specific settings: the Windows Update CSP's `AllowAutoUpdate` registry value, and `ExcludeWUDriversInQualityUpdate`. If either policy is misconfigured, the device is flagged. **Export** collects non-compliant devices and writes a CSV with device name, user, policy values, specific alert text, and the device ID for downstream remediation. The parallel processing (controlled by `-ThrottleLimit`) prevents graph throttling when scanning large estates. The script handles two common scenarios. First, when `AllowAutoUpdate` is set to 0 (notify for download) or 5 (disable automatic updates), Autopatch cannot push patches automatically—the policy overrides service behavior. Second, when `ExcludeWUDriversInQualityUpdate` is set to 1 (true), driver updates are explicitly removed from the quality update feed that Autopatch reads from. Both scenarios result in the device appearing "Ready" in the Autopatch portal while actually receiving no updates—a silent failure.

Usage & Parameters

Basic usage (scan all devices, save to Desktop):

./Analyze-AutopatchPolicyAlerts.ps1

Scan with custom output path:

./Analyze-AutopatchPolicyAlerts.ps1 -OutputPath "C:\reports\autopatch-alerts.csv"

Include compliant devices in the report:

./Analyze-AutopatchPolicyAlerts.ps1 -IncludeCompliant

Reduce parallel threads if Graph is rate-limiting you:

./Analyze-AutopatchPolicyAlerts.ps1 -ThrottleLimit 3

Sample output (console):

PS C:\> ./Analyze-AutopatchPolicyAlerts.ps1 [*] Windows Autopatch Policy Alert Analyzer v1.0 [*] Output will be saved to: C:\Users\admin\Desktop\autopatch-policy-report-20250509-143022.csv [*] Authenticating to Microsoft Graph... [+] Authentication successful [*] Querying Intune-managed devices... [+] Found 4853 managed devices ... [+] Policy scan complete: 47 non-compliant devices found [+] Report exported to: C:\Users\admin\Desktop\autopatch-policy-report-20250509-143022.csv [+] Total devices scanned: 4853 [+] Non-compliant devices: 47 === SUMMARY === Device Name User OS Version Last Sync AllowAutoUpdate Alerts ----------- ---- ---------- --------- ---------------- ------ LAPTOP-ABC123 john.smith@contoso.com Windows 11 2025-05-09 08:45:12 0 AllowAutoUpdate=0: Updates blocked (notify-only or disabled) DESKTOP-XYZ789 jane.doe@contoso.com Windows 10 2025-05-09 09:22:00 5 AllowAutoUpdate=5: Updates blocked (notify-only or disabled) | ExcludeWUDriversInQualityUpdate=1: Driver updates blocked WORKSTATION-456 m.johnson@contoso.com Windows 11 2025-05-09 07:15:33 Unknown ExcludeWUDriversInQualityUpdate=1: Driver updates blocked

The CSV output includes all 4,853 device records (or only the 47 non-compliant ones if you don't use `-IncludeCompliant`). Each row is ready for bulk remediation by your team.

Customization Ideas

  • Filter by organizational unit or user group: Add a `-Filter` parameter that chains with the device query: Get-MgDeviceManagementManagedDevice -Filter "userPrincipalName like '$OU%'" to scope scans by department.
  • Auto-remediate AllowAutoUpdate: Pipe non-compliant device IDs to a secondary script that uses New-MgDeviceManagementDeviceConfiguration to push a corrective policy (setting AllowAutoUpdate to 2 = "Auto download and notify").
  • Integrate with Teams notifications: After export, POST the non-compliant device count to a Teams webhook so your security team gets real-time alerts without checking a report.
  • Historical trending: Save each run's CSV with a timestamp and append to a master log; create a simple Excel chart showing non-compliance rate over 30 days to track remediation progress.
  • Email distribution: Wrap the export step in Send-MailMessage to email the CSV to patch managers as soon as the scan completes.

Common Autopatch Policy Failures Explained

Windows Update CSP Policy States AllowAutoUpdate 0 = Notify for Download User sees download prompt Requires manual action ❌ BLOCKS AUTOPATCH Policy overrides Autopatch 1 = Auto DL, Notify Restart Downloads automatically User chooses restart ✓ COMPATIBLE Autopatch can manage 2 = Auto Install, Restart Full automatic management Respects Autopatch rings ✓ OPTIMAL Recommended default 5 = Disabled Automatic updates off Manual patches only ❌ BLOCKS AUTOPATCH Complete failure mode ExcludeWUDriversInQualityUpdate 0 or Not Configured Driver updates included in quality update feed Autopatch delivers drivers ✓ CORRECT STATE 1 = True/Enabled Drivers excluded from quality update feed Autopatch CANNOT deliver ❌ BLOCKS DRIVERS ⚠ Why These Misconfigurations Happen • Legacy Group Policy (AllowAutoUpdate = 0) migrated to Intune without update • Third-party driver management (Lenovo Vantage, Dell Command Update) sets ExcludeWUDriversInQualityUpdate = 1 to prevent conflicts • Device not inheriting corrective policy due to scope tag filtering or exclusion rules
The five policy states and their Autopatch compatibility. States 0 and 5 (red borders) completely block Autopatch updates. ExcludeWUDriversInQualityUpdate = 1 specifically blocks driver patches. All green-bordered states allow Autopatch to function.

Remediation Workflow

Before Bulk Remediation Test your corrective policy on 5–10 pilot devices first. Monitor for 48 hours to confirm Autopatch ring assignments and update timing remain correct. If you're using third-party driver tools (Lenovo Vantage, Dell Command), coordinate with that team before changing ExcludeWUDriversInQualityUpdate.

Once you've identified non-compliant devices via the script, remediation follows three patterns:

Pattern 1: Fix AllowAutoUpdate via Intune Configuration Profile

  1. Create a Windows Update CSP Profile in Intune: Devices → Configuration Profiles → Create Profile → Platform: Windows 10/11 → Profile Type: "Settings Catalog" or "Custom ADMX"
  2. Set AllowAutoUpdate to 2 (Auto download and install with scheduled restart) or leave it "Not Configured" to allow Autopatch's default behavior
  3. Target the non-compliant devices via assignment rule or explicit device group
  4. Deploy and monitor: Check Intune portal → Device Compliance for policy application status within 15 minutes

Pattern 2: Fix ExcludeWUDriversInQualityUpdate

  1. Coordinate with driver management teams (check if Lenovo Vantage, Dell Command, or similar is actively managing drivers on the device)
  2. If you own driver updates: Create a profile setting ExcludeWUDriversInQualityUpdate to 0 or "Not Configured"
  3. If third-party tool is managing drivers: Disable that tool's auto-update, allow Autopatch to take over, or negotiate a co-management policy
  4. Deploy the policy and verify Autopatch driver rings appear in the device's update history within 7 days

Pattern 3: Verify Autopatch Ring Assignment (Hidden Issue)

A device can pass both policy checks but still fail to receive updates if it's not assigned to any Autopatch ring. In the Intune portal, navigate to Tenant Management → Windows Autopatch → Manage Devices and confirm each repaired device appears in at least one ring (Test, Preview, or Current).

Key API Properties Reference

Policy Setting CSP Path Valid Values Autopatch Impact Remediation
AllowAutoUpdate ./Device/Vendor/MSFT/Policy/Config/Update/AllowAutoUpdate 0–5, Not Configured Blocks if 0 or 5 Set to 1, 2, 3, or leave Not Configured
ExcludeWUDriversInQualityUpdate ./Device/Vendor/MSFT/Policy/Config/Update/ExcludeWUDriversInQualityUpdate 0 (false), 1 (true), Not Configured Blocks drivers if 1 Set to 0 or leave Not Configured
AllowAutoWindowsUpdateDownloadOverMeteredNetwork ./Device/Vendor/MSFT/Policy/Config/Update/AllowAutoDownloadOverMeteredNetwork 0, 1, Not Configured Does not block N/A — educational only
DeferFeatureUpdatesUntilDays ./Device/Vendor/MSFT/Policy/Config/Update/DeferFeatureUpdatesUntilDays 0–180 days Compatible with Autopatch rings Autopatch overrides; use rings instead

Troubleshooting & FAQs

Q: Devices show "Ready" in Autopatch but aren't getting updates The portal displays ready state based on enrollment and last-sync, not policy compliance. This script finds the hidden blockers. A device can be "Ready" and still be policy-blocked.
Q: My script times out on 10,000+ devices Increase `-ThrottleLimit` to 8–10, or split the query by organizational unit using the `-Filter` parameter to process smaller batches in parallel sessions.
Q: After remediation, updates still don't appear Check two things: (1) the policy deployment completed on the device (Device Details → Managed Devices → Configuration compliance), and (2) the device is assigned to an Autopatch ring (Windows Autopatch → Manage Devices). If both are correct, wait 24–48 hours for Autopatch's next evaluation cycle.

Production Deployment Checklist

  • ☐ Test the script against a test tenant or 50-device pilot first
  • ☐ Validate that Graph API scopes match your organization's conditional access policies
  • ☐ Schedule the script weekly as an Azure Automation runbook or Task Scheduler job to track trend over time
  • ☐ Set up RBAC so patch teams can run the script without global admin (Intune Administrator role is sufficient)
  • ☐ Export the CSV to a SharePoint list or Power BI dataset for dashboard visibility
  • ☐ Create a corresponding remediation runbook that patches devices automatically after approval
  • ☐ Document the expected detection lag: devices appear in alerts 24–72 hours after misconfiguration

The script and methodology in this article reflect real-world Intune patch management at scale. Organizations with 2,000+ devices often encounter these policy conflicts—especially when migrating from Group Policy or running third-party driver tools. Running this analysis monthly catches silent update failures before they turn into compliance incidents.

Was this article helpful?

🎓 Ready to go deeper?

Practice real MD-102 exam questions, get AI feedback on your weak areas, and fast-track your Intune certification.

Start Free Practice → Book a Session
Souhaiel Morhag
Souhaiel Morhag
Microsoft Endpoint & Modern Workplace Engineer

Souhaiel Morhag is a Microsoft Intune and endpoint management specialist with hands-on experience deploying and securing enterprise environments across Microsoft 365. He founded MSEndpoint.com to share practical, real-world guides for IT admins navigating Microsoft technologies — and built the MSEndpoint Academy at app.msendpoint.com/academy, a dedicated learning platform for professionals preparing for the MD-102 (Microsoft 365 Endpoint Administrator) certification. Through in-depth articles and AI-powered practice exams, Souhaiel helps IT teams move faster and certify with confidence.

Related Articles

Popular on MSEndpoint