Unattended Windows Update automation for fleet deployment. One self-contained PowerShell script installs every pending update, reboots as needed, resumes after boot, and cleans itself up when the machine is fully patched.
Runs headless as SYSTEM. No internet required on the endpoint.
Patching a fleet by hand does not scale, and the usual scripts break in the field: they hang on a hidden NuGet prompt when run as SYSTEM, they loop forever when Windows Update re-offers an update that never applies, and they report success the moment a process spawns whether or not it actually ran.
AutoPatch fixes those. It runs headless as SYSTEM, needs no internet on the endpoint, and tells the truth about whether it is working.
- Zero dependencies on the endpoint. The PSWindowsUpdate module is bundled inside the script as a base64 zip. No NuGet, no PSGallery, no download, no prompt to hang on.
- Full patch loop. Scan, install, reboot if required, resume after boot, repeat until clean. Includes drivers and firmware.
- Loop detection with self-heal. Fingerprints each pass. If Windows Update re-offers the same set, it resets the update datastore once, then flags true un-installables and exits instead of spinning forever.
- Honest status. The deploy waits for the scanner to check in before reporting success. No false greens.
- Every blocking call is bounded. Freeze check, network probe, and cleanup delay all have hard timeouts. Nothing hangs indefinitely.
- Self-cleanup. After 30 continuous minutes with nothing left to install, it deletes its task and working files. The log survives.
- Live viewer. Watch phase, current update, and progress on any machine.
- Edit the source: DEPLOY-AutoPatch-v8.7.3.source.ps1
- Build the file: .\Build-Deploy.ps1
- Paste DEPLOY-AutoPatch-v8.7.3.ps1 into your RMM and run as SYSTEM
The machine patches itself and cleans up when done.
DEPLOY-AutoPatch-v8.7.3.source.ps1 The source. All logic lives here (~40KB). Edit this one.
PSWindowsUpdate-2.2.1.5.b64 The module zip, base64-encoded. Injected at build time. Only touch it to update the module.
Build-Deploy.ps1 Splices the module blob into the source and emits the deployable. Rarely edited.
DEPLOY-AutoPatch-v8.7.3.ps1 Generated output (~340KB). The single file you deploy. Never hand-edit, rebuild instead.
The build validates the blob (real base64, zip magic), replaces exactly one {{MODULE_ZIP_B64}} token line, and parse-checks the output before declaring it deployable. If the built file and source ever disagree, the source wins.
- Creates C:\autopatch\ and locks its ACLs (SYSTEM and Admins full, Users read-only). The tree runs as SYSTEM, so it must not be user-writable.
- Writes the scanner and the viewer.
- Extracts the bundled module with .NET ZipFile (no Expand-Archive, no download).
- Registers the AutoPatch startup task and launches the scanner.
- The scanner loops until the machine is fully patched, then removes itself.
Watch a machine:
powershell -ExecutionPolicy Bypass -File C:\autopatch\updater\WATCH-AutoPatch.ps1
Or read the log directly at C:\autopatch\AutoPatchLog.txt. Every step logs before it runs, so a stall always shows its last position.
- Windows 10 / 11, PowerShell 5.1+
- Run as SYSTEM (standard RMM default). No internet required on the endpoint.
- Application allowlisting (optional): allow execution under C:\autopatch.
- Reboot-freeze tooling (optional): machines must be thawed. The scanner checks DFC.exe, aborts if frozen, and skips the check entirely on machines without it.
- Module bundled, not installed. Install-Module raises a hidden Y/N NuGet prompt that hangs forever under SYSTEM. Bundling removes the network from the picture.
- Feature upgrades skipped. Version jumps (24H2 to 25H2, etc.) are held off for freeze safety. Install those manually.
- Plain Get-WindowsUpdate. The -MicrosoftUpdate flag pulled stale driver offers that never committed and caused an infinite re-offer loop.
Deploy seems stalled Last line of C:\autopatch\AutoPatchLog.txt
PSWindowsUpdate unavailable Blob missing or corrupt. Rebuild and redeploy.
Deep Freeze: FROZEN Thaw the machine, rerun.
Updates once, never resumes Deploy output for "could not register startup task".
Same updates re-offered 3+ passes Self-heals once, then flags un-installables and finishes.
MIT.