Zero-XAtlasHelp

Script library ›

Reset-WindowsUpdateAgent

Reset the Windows Update agent. Stops the update services, renames the SoftwareDistribution and catroot2 folders so Windows rebuilds them, and starts the services again.

needs adminsupports -WhatIfrisk: lowversion 1written by an assistant from cited pages
untested here · 0 fixed, 0 not

Fixes these codes

0x80071A910x80240439

What it does

Use this when updates fail to scan, download or install and Microsoft's guidance for the error says to reset the update agent (for example 0x80242006, 0x80240439, 0x80070005, 0x80071A91, 0x8024001E).

The script stops the update services, renames the SoftwareDistribution and catroot2 folders to .old so Windows builds fresh ones, then starts the services again. Nothing is deleted. To undo it, stop the services and rename the .old folders back.

Parameters

Examples

.\Reset-WindowsUpdateAgent.ps1 -WhatIf

Shows what would happen and changes nothing.

.\Reset-WindowsUpdateAgent.ps1

Runs the reset and asks before each change.

Microsoft's guidance

The script

Click the script to select all of it, then copy. Fingerprint of this text (SHA-256): b543d434e54868c18bce2975fcce9df0427cec39fbdd0d3d2682e7339716cf4c. Updated 2026-10-21.

# Copyright (c) 2026 Owen Perry. All rights reserved.
#Requires -Version 5.1
#Requires -RunAsAdministrator

<#
.SYNOPSIS
Resets the Windows Update agent.

.DESCRIPTION
Use this when updates fail to scan, download or install and Microsoft's guidance for the error says to reset the update agent
(for example 0x80242006, 0x80240439, 0x80070005, 0x80071A91, 0x8024001E).

The script stops the update services, renames the SoftwareDistribution and catroot2 folders to .old so Windows builds fresh ones,
then starts the services again. Nothing is deleted. To undo it, stop the services and rename the .old folders back.

.PARAMETER RemoveOldBackup
Deletes SoftwareDistribution.old and catroot2.old left by an earlier run. Without this switch the script stops if they exist.

.EXAMPLE
.\Reset-WindowsUpdateAgent.ps1 -WhatIf
Shows what would happen and changes nothing.

.EXAMPLE
.\Reset-WindowsUpdateAgent.ps1
Runs the reset and asks before each change.

.LINK
https://learn.microsoft.com/en-us/troubleshoot/windows-client/installing-updates-features-roles/troubleshoot-windows-update-error-0x80240439
#>

# SupportsShouldProcess adds the -WhatIf and -Confirm switches.
[CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')]
param([switch]$RemoveOldBackup)

# Stop at the first error instead of carrying on.
$ErrorActionPreference = 'Stop'

# Keep a log of what the script does. -WhatIf:$false makes sure the log is still written during a -WhatIf run.
$logFolder = Join-Path $env:ProgramData 'Zero-X\logs'
New-Item -ItemType Directory -Path $logFolder -Force -WhatIf:$false | Out-Null
$logging = $false
try {
    $logFile = Join-Path $logFolder ('Reset-WindowsUpdateAgent-{0:yyyyMMdd-HHmmss}.log' -f (Get-Date))
    Start-Transcript -Path $logFile -WhatIf:$false | Out-Null
    $logging = $true
} catch {
    Write-Warning "No log file: $($_.Exception.Message)"
}

$serviceNames = 'wuauserv', 'bits', 'cryptSvc'          # Windows Update, BITS, Cryptographic Services
$dataStore = Join-Path $env:windir 'SoftwareDistribution'
$cryptoCache = Join-Path $env:windir 'System32\catroot2'
$failed = $false

try {
    # Microsoft says to delete the .old folders before running the reset a second time.
    foreach ($oldFolder in "$dataStore.old", "$cryptoCache.old") {
        if (Test-Path -LiteralPath $oldFolder) {
            if (-not $RemoveOldBackup) {
                throw "$oldFolder is left over from an earlier run. Run again with -RemoveOldBackup to delete it first."
            }
            if ($PSCmdlet.ShouldProcess($oldFolder, 'Delete')) {
                Remove-Item -LiteralPath $oldFolder -Recurse -Force
            }
        }
    }

    # Stop the services so the folders are not in use.
    foreach ($name in $serviceNames) {
        if ($PSCmdlet.ShouldProcess($name, 'Stop service')) {
            Stop-Service -Name $name -Force
            (Get-Service -Name $name).WaitForStatus('Stopped', '00:01:00')
        }
    }

    # Rename the folders. Windows creates new ones the next time the services start.
    foreach ($item in @(@($dataStore, 'SoftwareDistribution.old'), @($cryptoCache, 'catroot2.old'))) {
        $path, $newName = $item
        if (-not (Test-Path -LiteralPath $path)) {
            Write-Warning "$path does not exist, so there is nothing to rename."
        } elseif ($PSCmdlet.ShouldProcess($path, "Rename to $newName")) {
            Rename-Item -LiteralPath $path -NewName $newName
        }
    }
} catch {
    $failed = $true
    Write-Error $_
} finally {
    # Always start the services again, even if a step above failed.
    foreach ($name in 'cryptSvc', 'bits', 'wuauserv') {
        try {
            if ($PSCmdlet.ShouldProcess($name, 'Start service')) {
                Start-Service -Name $name
                (Get-Service -Name $name).WaitForStatus('Running', '00:01:00')
            }
        } catch {
            $failed = $true
            Write-Warning "Could not start ${name}: $($_.Exception.Message)"
        }
    }
    if ($logging) { Stop-Transcript | Out-Null }
}

if ($failed) { exit 1 }
if (-not $WhatIfPreference) {
    Write-Host 'Done. Try the update again.'
}
Tested this in a lab? Record the result
(Enterprise subscription only)