Windows Autopatch – Auto Remediation Script

Introduction

In the complex ecosystem of modern IT environments, ensuring the smooth deployment of Windows Updates using Windows Autopatch is critical for maintaining system security and performance. However, IT Administrators often encounter roadblocks – policy conflicts that prevent the successful deployment of Windows Quality and Feature Updates. These conflicts are especially prevalent in environments that utilized Configuration Manager, Group Policy Objects (GPO), and Windows Server Update Services (WSUS) for updates. The transition to modern management through Co-Management and shifting the control slider to Intune, a required step to enable Windows Autopatch, does not always clear the remnants of legacy configurations, leaving behind artifacts in the registry that can disrupt the service operations. 

A very common configuration mistake I see sometimes at customers using Configuration Manager (ConfigMgr),  is that they still have the Software Update client settings enabled in ConfigMgr, this could cause conflict with Windows Autopatch policies. To ensure that Software Update Policies don’t conflict with Windows Autopatch policies, make sure you target your Autopatch devices with a client setting that:

  • Disable Windows and Office updates.
  • Includes devices enrolled into Autopatch to remove any existing configuration(s).

I have also seen perfect configured environments, but with some left over artifacts in the registry. The Solution below will make sure that Update Policy related registry artifacts are remediated.

Recognizing this gap and seen many peoples struggle with this, I would like to share a solution tailored to address these challenges head-on. Our approach consists of a Detection Script that identifies unnecessary registry keys, a Remediation Script that removes them and an logging mechanism. The generated log files are stored in the Intune Management Extension (IMEI) folder C:\ProgramData\Microsoft\IntuneManagementExtension\Logs, simplifying the diagnostic process and allowing for easy collection through Intune. The solution is based on the recommendations that are in the docs. Read more Conflicting configurations – Windows Deployment | Microsoft Learn.

The Detection Script

This PowerShell script performs several operations to detect and log specific Windows Update policy settings that could prevent updates from being deployed correctly with Windows Autopatch. Here’s a step-by-step breakdown of what the script does:

  1. Define Log Location and Name: It sets up variables for the path ($TranscriptPath) and name ($TranscriptName) of the log file where it will store the output. These point to a log file named “AutoPatchDetection.log” within the “C:\ProgramData\Microsoft\IntuneManagementExtension\Logs” directory.
  2. Create Log Directory (If Necessary): It attempts to create the directory specified by $TranscriptPath if it doesn’t already exist, using the -Force parameter to overwrite any existing files without prompting for confirmation.
  3. Stop Orphaned Transcripts: It tries to stop any existing PowerShell transcription (logging) sessions that might have been left running. If there’s no active transcript session, it catches the resulting error and does nothing, preventing the script from stopping.
  4. Start Transcription: It begins a new transcription session, saving the output to the specified log file and appending to it if it already exists.
  5. Initialize Registry Key Array: It creates an array ($regkeys) to hold objects representing specific registry keys related to Windows Update policies. Each object contains a Name and a path indicating the registry key’s location and the value it’s looking for.
  6. Populate Array with Key Information: It adds objects to the array representing the registry keys:
    • DoNotConnectToWindowsUpdateInternetLocations
    • DisableWindowsUpdateAccess
    • WUServer
    • UseWUServer
    • NoAutoUpdate These keys are associated with policies that can restrict Windows Update functionality.
  7. Check Registry Settings: It iterates over each object in the $regkeys array, checking if the specified registry key exists and contains the specified property (policy setting). If it finds a key that matches, it sets a flag ($RemediationNeeded) to indicate that incorrect registry settings were found and logs this information.
  8. Log and Exit Based on Findings:
    • If any incorrect settings were detected ($RemediationNeeded -eq $true), it logs that the registry settings are incorrect, stops the transcript (logging), and exits with code 1, indicating an error or issue was found.
    • If no incorrect settings were found, it logs that the registry settings are correct, stops the transcript, and exits with code 0, indicating success.
$TranscriptPath = "C:\ProgramData\Microsoft\IntuneManagementExtension\Logs"
$TranscriptName = "AutoPatchDetection.log"
new-item $TranscriptPath -ItemType Directory -Force

# stopping orphaned transcripts
try
{
    stop-transcript|out-null
}
  catch [System.InvalidOperationException]
{}

Start-Transcript -Path $TranscriptPath\$TranscriptName -Append

# initialize the array
[PsObject[]]$regkeys = @()
# populate the array with each object
$regkeys += [PsObject]@{ Name = "DoNotConnectToWindowsUpdateInternetLocations"; path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\"}
$regkeys += [PsObject]@{ Name = "DisableWindowsUpdateAccess"; path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\"}
$regkeys += [PsObject]@{ Name = "WUServer"; path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\"}
$regkeys += [PsObject]@{ Name = "UseWUServer"; path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU\"}
$regkeys += [PsObject]@{ Name = "NoAutoUpdate"; path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU\"}

foreach ($setting in $regkeys)
{
    write-host "checking $($setting.name)"
    if((Get-Item $setting.path -ErrorAction Ignore).Property  -contains $setting.name)
    {
        write-host "$($setting.name) is not correct"
        $RemediationNeeded = $true
    }
}

if ($RemediationNeeded -eq $true)
{
    write-host "registry settings are incorrect"
    Stop-Transcript
    exit 1
}
else 
{
    write-host "registry settings are correct"
    Stop-Transcript
    exit 0
}

You can just copy the code here, or if you want to participate get it from GitHub https://github.com/KenGoossens/AutopatchRemediationScripts/blob/main/AP_DetectionScripts.ps1

The Remediation Script

This PowerShell script is designed to remediate Windows Update policy conflicts by removing specific registry keys that can prevent updates from being deployed successfully. Here’s a detailed explanation of its operation:

  1. Set Up Log File: It establishes a directory and a file name for logging purposes, targeting “C:\ProgramData\Microsoft\IntuneManagementExtension\Logs\AutoPatchRemediation.log” as the file where the script’s output will be recorded.
  2. Create Log Directory (If Necessary): The script ensures the existence of the specified directory for the log file, creating it if it doesn’t already exist and using the -Force parameter to override any potential issues without prompting.
  3. Stop Orphaned Transcripts: It attempts to stop any transcription (logging) sessions that might have been left running previously. If no such session is active, and an error occurs, it catches the error to prevent the script from failing at this point.
  4. Start New Transcription: Begins logging the script’s output to the specified log file, appending to it if the file already exists, to record all actions taken by the script.
  5. Initialize Registry Key Array: It initializes an array to hold objects, each representing a specific registry key related to Windows Update policies that might cause conflicts.
  6. Populate Array with Target Keys: The script adds several objects to this array, each specifying the Name and path of a registry key that potentially conflicts with Windows updates, including:
    • DoNotConnectToWindowsUpdateInternetLocations
    • DisableWindowsUpdateAccess
    • WUServer
    • UseWUServer
    • NoAutoUpdate
  7. Remediate Conflicts: For each registry key object in the array, the script:
    • Checks if the specified key exists and contains the property (name) indicated.
    • If the property exists, indicating a potential policy conflict, the script removes this property from the registry to remediate the conflict, logging this action.
    • If the property does not exist, it logs that the specific setting was not found, indicating no action is needed for that key.
  8. Stop Transcription: Once all specified registry keys have been checked and remediated as necessary, the script stops logging its actions and closes the log file.
$TranscriptPath = "C:\ProgramData\Microsoft\IntuneManagementExtension\Logs"
$TranscriptName = "AutoPatchRemediation.log"
new-item $TranscriptPath -ItemType Directory -Force

# stopping orphaned transcripts
try
{
    stop-transcript|out-null
}
  catch [System.InvalidOperationException]
{}

Start-Transcript -Path $TranscriptPath\$TranscriptName -Append

# initialize the array
[PsObject[]]$regkeys = @()
# populate the array with each object
$regkeys += [PsObject]@{ Name = "DoNotConnectToWindowsUpdateInternetLocations"; path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\"}
$regkeys += [PsObject]@{ Name = "DisableWindowsUpdateAccess"; path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\"}
$regkeys += [PsObject]@{ Name = "WUServer"; path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\"}
$regkeys += [PsObject]@{ Name = "UseWUServer"; path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU\"}
$regkeys += [PsObject]@{ Name = "NoAutoUpdate"; path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU\"}

foreach ($setting in $regkeys)
{
    write-host "checking $($setting.name)"
    if((Get-Item $setting.path -ErrorAction Ignore).Property -contains $setting.name)
    {
        write-host "remediating $($setting.name)"
        Remove-ItemProperty -Path $setting.path -Name $($setting.name)
    }
    else
    {
        write-host "$($setting.name) was not found"
    }
}
Stop-Transcript

You can just copy the code here, or if you want to participate get it from GitHub https://github.com/KenGoossens/AutopatchRemediationScripts/blob/main/AP_RemediationScripts.ps1

The Implementation

Now let us focus on the careful execution of our developed solution, focusing on deploying the Detection and Remediation Scripts through Intune, and ensuring precise configuration adjustments. Our objective is clear – resolving policy conflicts and enhancing Windows update deployments with Windows Autopatch.

Uploading and Deploying the Scripts in Intune

    1. Sign into https://intune.microsoft.com
    2. Navigate to Devices: Go to the “Devices” section.
    3. Select Scripts and remediations: Under “Devices”, look for the “Scripts and remediations” section. You will have the option to choose between “Remediations” and “Platform scripts”. Select “Remediations”.
    4. Create: Click on “Create” to create a new custom script.
    5. For Create custom script, let us go step-by-step through the wizard:
        • In the “Basics” tab, you only need to provide a “Name” for your script:
          • Name: Enter the “Name” of your remediation script.
          • Description (optional): Enter a description providing a little detail of the remediation script.
          • Publisher(auto): This one is automatically filled in, but can be changed.
          • Version: Versioning of scripts is crucial because it allows for tracking changes and ensuring consistency across deployments.
        • In the “Settings” tab, we add our detection and remediation scripts to the solution:
          • Add Detection script: click on the blue folder icon to browse for your “detection script” and open it. This will add the script.
          • Add Remediation script: click on the blue folder icon to browse for the “remediation script” and open it. This will add the script.
        • Scroll down on the page if you don’t see the options below, and make sure they are all set to “No” (Should be the default setting)
          • Run this script using the logged-on credentials: No
          • Enforce script signature check: No
          • Run script in 64-bit PowerShell: No
        • In the “Scope tags” tab, you can select your scope tags, some of you might use them others might not. I will skip this step and move on to the assignment.
        • In the “Assignment tab”, we configure the deployment options:
          • Assign To: Here you can select “All Users” or “All Devices”, we are not going to use that, so you can ignore this option.
          • Assignment Group: Select the “Windows Autopatch – Devices All” group, that will ensure that we target all devices registered in the Windows Autopatch Service.
          • Schedule: Click on “Daily” to edit the schedule for your remediation. You have multiple options to run the script, I run this script every hour, to make sure that drifts are being remediated:
            • Once, Hourly and Daily
            • Repeat every x days
            • Start Time
          • Filter:  You can use filters to assign a policy based on rules you created earlier. We are not using filters in this guide.
          • Filter mode: Here you select if you want to Include or Exclude the groups that receive the filter assignment.
      • Click Next to review your settings and to create your remediation script.
      • Click Create and if all goes as planned, you will now have your remediation script created and assigned to all your Windows Autopatch devices.

    Monitoring

    After deployment, monitor the execution status and outcomes of your scripts through the “Device status” page within the Proactive remediation script blade. Intune provides detailed reporting on whether scripts were successfully executed and the results of those executions. If you click on the “Script package name” in the Remediations blade, you will get some information about how your script package is performing.

    Would you like to have more insights in the “Detection Status” and “Remediations Status”, go check the Overview page

    Collection Log Files

    Because we have some intelligence built-in to our scripts, we have some logfiles that are being saved in the IMEI Log folder. That allows us to use the Collect Diagnostic function in Intune to obtain the logfiles dumped by the Detection and Remediation script. Below the steps to collect and read the logs.

      • Navigate to Devices: Go to the “All devices” section.
      • Search your device: Under “All devices”, enter your device name in the search bar.
      • Open the device info: Click on the device name to open the device information blade.
      • Collect Diagnostics: Intune will try to collect the diagnostics from the device.
      • Check for Status Complete and Download Diagnostics: You might want to hit F5 a couple times to speed up the refresh in the console – Once the status change to “Complete” and the diagnostic files are uploaded to the blob, you can download the zip file from the “Device diagnostic page”.
      • Open the zip and search for the IntuneManagementExtension_Logs folder. That folder contains our two logfiles created by the remediation script. If no remediation was required you will have only the detection log.
      • If you want to know if the remediations were executed, search for “remediating” in the autopatchremediation.log file. You will notice that every check is listed in the log and whenever a drift is detected it will flag for remediate (detection script) or remediation the drift.

      I hope this will help you to quickly implement this remediation, if you happen to encounter this problem in your environment.

      Make sure to test this in your environment to a small set of devices before pushing it out.

      Let me know if you need any help. I’m available on X my tag is @Goosken

    You must be logged in to post a comment.