Managed IT • Knoxville, TN
Windows Update Reset
automation
dateNov 29, 2024
statusRESOLVED
Incident

HR director's laptop stuck in reboot loop for 6 hours. Windows 11 24H2 feature update would install to 47%, then roll back with "We couldn't complete the updates. Undoing changes." Machine unusable during benefits enrollment deadline. Windows Update troubleshooter did nothing. DISM couldn't find source files. Every standard fix failed.

Assessment
initial state:
update failure ···· 24H2 failing consistently at 47%
error code ········ 0x80070002 - "file not found"
disk space ········ 89GB free - not a space issue
SoftwareDistribution · 12GB corrupted download fragments

User had force-restarted during a previous update attempt two weeks ago. That interrupted update left behind corrupted component store entries poisoning every subsequent update attempt.

What We Tried First
[X] WU Troubleshooter ·· "components must be repaired" - did nothing
[X] DISM /RestoreHealth · failed 0x800f081f - no source files
[X] SFC /scannow ········ found corrupt, couldn't fix without DISM
[X] delete SoftwareDistribution · service wouldn't stop
[X] safe mode cleanup ··· corruption had spread to catroot2 and BITS

Corruption had cascaded. Partial fix attempts made it worse. Needed to reset everything at once - services, caches, DLL registrations, security descriptors, network stack. The nuclear option.

Solution

Booted to Safe Mode with Networking, connected via RMM, ran this script. Same procedure Microsoft support would walk through over 2 hours - automated in 90 seconds.

[+] windows_update_reset.ps1GitHub
$ErrorActionPreference = 'Stop'

<#
██╗     ██╗███╗   ███╗███████╗██╗  ██╗ █████╗ ██╗    ██╗██╗  ██╗
██║     ██║████╗ ████║██╔════╝██║  ██║██╔══██╗██║    ██║██║ ██╔╝
██║     ██║██╔████╔██║█████╗  ███████║███████║██║ █╗ ██║█████╔╝
██║     ██║██║╚██╔╝██║██╔══╝  ██╔══██║██╔══██║██║███╗██║██╔═██╗
███████╗██║██║ ╚═╝ ██║███████╗██║  ██║██║  ██║╚███╔███╔╝██║  ██╗
╚══════╝╚═╝╚═╝     ╚═╝╚══════╝╚═╝  ╚═╝╚═╝  ╚═╝ ╚══╝╚══╝ ╚═╝  ╚═╝
================================================================================
 SCRIPT   : Windows Update Reset                                         v1.0.2
 AUTHOR   : Limehawk.io
 DATE      : January 2026
 USAGE    : .\windows_update_reset.ps1
================================================================================
 FILE     : windows_update_reset.ps1
DESCRIPTION : Resets Windows Update components and clears cache
--------------------------------------------------------------------------------
 README
--------------------------------------------------------------------------------
 PURPOSE

 Completely resets Windows Update components by stopping services, clearing
 caches, resetting security descriptors, re-registering DLLs, and restarting
 services. Fixes most Windows Update problems.

 DATA SOURCES & PRIORITY

 1) Hardcoded values (defined within the script body)
 2) Windows Update services and components

 REQUIRED INPUTS

 - RebootAfterReset : Whether to reboot after reset (default: $false)

 SETTINGS

 - Stops: BITS, wuauserv, appidsvc, cryptsvc
 - Clears: SoftwareDistribution, catroot2, QMGR data
 - Resets: BITS and wuauserv security descriptors
 - Registers: 30+ Windows Update related DLLs
 - Resets: Winsock

 BEHAVIOR

 1. Stops all Windows Update related services
 2. Flushes DNS cache
 3. Clears BITS download queue data
 4. Renames SoftwareDistribution and catroot2 folders
 5. Resets Windows Update policies in registry
 6. Resets BITS and wuauserv security descriptors
 7. Re-registers all Windows Update DLLs
 8. Resets Winsock
 9. Restarts all services
 10. Optionally reboots system

 PREREQUISITES

 - Windows 10/11
 - Admin privileges required
 - Internet connectivity for updates after reset

 SECURITY NOTES

 - No secrets in logs
 - Modifies system registry and service configurations
 - Creates .bak folders for recovery

 EXIT CODES

 - 0: Success
 - 1: Failure

 EXAMPLE RUN

 [INFO] INPUT VALIDATION
 ==============================================================
 Reboot After Reset : False

 [RUN] STOPPING SERVICES
 ==============================================================
 Stopping BITS...
 Stopping wuauserv...
 Stopping appidsvc...
 Stopping cryptsvc...

 [RUN] CLEARING CACHES
 ==============================================================
 Flushing DNS...
 Clearing QMGR data...
 Renaming SoftwareDistribution...
 Renaming catroot2...

 [RUN] RESETTING COMPONENTS
 ==============================================================
 Resetting security descriptors...
 Re-registering DLLs...
 Resetting Winsock...

 [RUN] STARTING SERVICES
 ==============================================================
 Starting BITS...
 Starting wuauserv...
 Starting appidsvc...
 Starting cryptsvc...

 [OK] RESULT
 ==============================================================
 Status : Success

 [OK] SCRIPT COMPLETED
 ==============================================================
--------------------------------------------------------------------------------
 CHANGELOG
--------------------------------------------------------------------------------
 2026-01-19 v1.0.2 Updated to two-line ASCII console output style
 2025-12-23 v1.0.1 Updated to Limehawk Script Framework
 2025-11-29 v1.0.0 Initial Style A implementation
================================================================================
#>

Set-StrictMode -Version Latest

# ==== STATE ====
$errorOccurred = $false
$errorText = ""

# ==== HARDCODED INPUTS ====
$RebootAfterReset = $false

# ==== ADMIN CHECK ====
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
if (-not $isAdmin) {
    Write-Host ""
    Write-Host "[ERROR] ADMIN PRIVILEGES REQUIRED"
    Write-Host "=============================================================="
    Write-Host "Script requires admin privileges."
    Write-Host "Please relaunch as Administrator."
    exit 1
}

# ==== RUNTIME OUTPUT ====
Write-Host ""
Write-Host "[INFO] INPUT VALIDATION"
Write-Host "=============================================================="
Write-Host "Reboot After Reset : $RebootAfterReset"

# ==== STOP SERVICES ====
Write-Host ""
Write-Host "[RUN] STOPPING SERVICES"
Write-Host "=============================================================="

$services = @('bits', 'wuauserv', 'appidsvc', 'cryptsvc')
foreach ($svc in $services) {
    Write-Host "Stopping $svc..."
    Stop-Service -Name $svc -Force -ErrorAction SilentlyContinue
    $retries = 0
    while ((Get-Service -Name $svc -ErrorAction SilentlyContinue).Status -ne 'Stopped' -and $retries -lt 3) {
        Start-Sleep -Seconds 2
        Stop-Service -Name $svc -Force -ErrorAction SilentlyContinue
        $retries++
    }
}

# ==== CLEAR CACHES ====
Write-Host ""
Write-Host "[RUN] CLEARING CACHES"
Write-Host "=============================================================="

try {
    Write-Host "Flushing DNS..."
    ipconfig /flushdns | Out-Null

    Write-Host "Clearing QMGR data..."
    Remove-Item -Path "$env:ALLUSERSPROFILE\Application Data\Microsoft\Network\Downloader\qmgr*.dat" -Force -ErrorAction SilentlyContinue
    Remove-Item -Path "$env:ALLUSERSPROFILE\Microsoft\Network\Downloader\qmgr*.dat" -Force -ErrorAction SilentlyContinue

    Write-Host "Clearing Windows Update logs..."
    Remove-Item -Path "$env:SYSTEMROOT\Logs\WindowsUpdate\*" -Recurse -Force -ErrorAction SilentlyContinue

    # Rename SoftwareDistribution
    Write-Host "Renaming SoftwareDistribution..."
    $sdPath = "$env:SYSTEMROOT\SoftwareDistribution"
    $sdBackup = "$env:SYSTEMROOT\SoftwareDistribution.bak"
    if (Test-Path $sdBackup) {
        Remove-Item -Path $sdBackup -Recurse -Force -ErrorAction SilentlyContinue
    }
    if (Test-Path $sdPath) {
        Rename-Item -Path $sdPath -NewName "SoftwareDistribution.bak" -Force -ErrorAction Stop
    }

    # Rename catroot2
    Write-Host "Renaming catroot2..."
    $crPath = "$env:SYSTEMROOT\System32\catroot2"
    $crBackup = "$env:SYSTEMROOT\System32\catroot2.bak"
    if (Test-Path $crBackup) {
        Remove-Item -Path $crBackup -Recurse -Force -ErrorAction SilentlyContinue
    }
    if (Test-Path $crPath) {
        Rename-Item -Path $crPath -NewName "catroot2.bak" -Force -ErrorAction Stop
    }

} catch {
    Write-Host "Warning: Some cache operations failed: $($_.Exception.Message)"
}

# ==== RESET COMPONENTS ====
Write-Host ""
Write-Host "[RUN] RESETTING COMPONENTS"
Write-Host "=============================================================="

try {
    # Reset Windows Update policies
    Write-Host "Resetting Windows Update policies..."
    $regPaths = @(
        "HKCU:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate",
        "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\WindowsUpdate",
        "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate",
        "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\WindowsUpdate"
    )
    foreach ($path in $regPaths) {
        if (Test-Path $path) {
            Remove-Item -Path $path -Recurse -Force -ErrorAction SilentlyContinue
        }
    }

    # Reset security descriptors
    Write-Host "Resetting service security descriptors..."
    sc.exe sdset bits "D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;AU)(A;;CCLCSWRPWPDTLOCRRC;;;PU)" | Out-Null
    sc.exe sdset wuauserv "D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;AU)(A;;CCLCSWRPWPDTLOCRRC;;;PU)" | Out-Null

    # Re-register DLLs
    Write-Host "Re-registering Windows Update DLLs..."
    $dlls = @(
        "atl.dll", "urlmon.dll", "mshtml.dll", "shdocvw.dll", "browseui.dll",
        "jscript.dll", "vbscript.dll", "scrrun.dll", "msxml.dll", "msxml3.dll",
        "msxml6.dll", "actxprxy.dll", "softpub.dll", "wintrust.dll", "dssenh.dll",
        "rsaenh.dll", "gpkcsp.dll", "sccbase.dll", "slbcsp.dll", "cryptdlg.dll",
        "oleaut32.dll", "ole32.dll", "shell32.dll", "initpki.dll", "wuapi.dll",
        "wuaueng.dll", "wuaueng1.dll", "wucltui.dll", "wups.dll", "wups2.dll",
        "wuweb.dll", "qmgr.dll", "qmgrprxy.dll", "wucltux.dll", "muweb.dll",
        "wuwebv.dll", "wudriver.dll"
    )
    $system32 = "$env:SYSTEMROOT\System32"
    foreach ($dll in $dlls) {
        $dllPath = Join-Path $system32 $dll
        if (Test-Path $dllPath) {
            regsvr32.exe /s $dllPath 2>$null
        }
    }

    # Reset Winsock
    Write-Host "Resetting Winsock..."
    netsh winsock reset | Out-Null
    netsh winsock reset proxy | Out-Null

    # Set services to auto start
    Write-Host "Configuring service startup types..."
    sc.exe config wuauserv start= auto | Out-Null
    sc.exe config bits start= auto | Out-Null
    sc.exe config DcomLaunch start= auto | Out-Null

} catch {
    $errorOccurred = $true
    $errorText = $_.Exception.Message
}

# ==== START SERVICES ====
Write-Host ""
Write-Host "[RUN] STARTING SERVICES"
Write-Host "=============================================================="

foreach ($svc in $services) {
    Write-Host "Starting $svc..."
    Start-Service -Name $svc -ErrorAction SilentlyContinue
}

if ($errorOccurred) {
    Write-Host ""
    Write-Host "[WARN] ERRORS OCCURRED"
    Write-Host "=============================================================="
    Write-Host $errorText
}

if ($errorOccurred) {
    Write-Host ""
    Write-Host "[WARN] RESULT"
    Write-Host "=============================================================="
    Write-Host "Status : Partial Success (some operations failed)"
} else {
    Write-Host ""
    Write-Host "[OK] RESULT"
    Write-Host "=============================================================="
    Write-Host "Status : Success"
}

Write-Host ""
Write-Host "[INFO] FINAL STATUS"
Write-Host "=============================================================="
Write-Host "Windows Update components have been reset."
Write-Host "A reboot is recommended to complete the process."

if ($RebootAfterReset) {
    Write-Host "Initiating reboot in 60 seconds..."
    shutdown /g /f /t 60 /c "Windows Update reset complete. Rebooting..."
}

if ($errorOccurred) {
    Write-Host ""
    Write-Host "[WARN] SCRIPT COMPLETED"
    Write-Host "=============================================================="
} else {
    Write-Host ""
    Write-Host "[OK] SCRIPT COMPLETED"
    Write-Host "=============================================================="
}

if ($errorOccurred) {
    exit 1
} else {
    exit 0
}
What Each Phase Does
1. stop services ···· BITS, wuauserv, appidsvc, cryptsvc
2. flush DNS ········ clears stale Microsoft update server entries
3. clear QMGR data ·· purges corrupted BITS download queue
4. rename SoftwareDistribution · forces rebuild of download cache
5. rename catroot2 ··· resets signature verification database
6. reset security ··· restores default permissions
7. re-register DLLs ·· fixes 15 critical COM registrations
8. reset Winsock ····· clears network catalog corruption

Why Safe Mode: Ensures no third-party software holds locks on WU components. Also prevents update service from auto-restarting mid-reset.

Outcome
total time to fix2 hours 13 min (including failed tries)
script runtime87 seconds
deadline metyes (47 minutes to spare)

Script completed, rebooted to normal mode, waited 10 minutes for Windows to rebuild update database. 24H2 feature update downloaded fresh, installed successfully on first attempt.

takeaways:
force-restarting during updates creates spreading corruption
when DISM can't find sources, component store itself is corrupted
nuclear reset resolves ~90% of failures that resist standard fixes
run in Safe Mode to avoid service lock conflicts
Get Help

Windows Update issues across your fleet? We deploy automated diagnostics and fixes that resolve failures without manual intervention.

Contact Us