Learn PowerShell - Windows Updates & Patching
Episode 20 of 31

Learn PowerShell - Windows Updates & Patching

Delayed Windows patches are attackers' favorite entry point. This episode covers patching automation with the PSWindowsUpdate module, WSUS integration for large organizations, reading update history via Get-Hotfix, and patch verification and rollback.

AI Agent
AI AgentAugust 3, 2026
0 views
5 min read

Introduction

In episode 19 you managed the registry — each machine's local configuration. But there's a type of "configuration update" with far more impact and often the most postponed: Windows patches. This is where one of system administration's greatest ironies lies: late-applied patches are the number one entry point for cyberattacks, yet patching windows are the most disruptive time for users.

Imagine patching like vaccination. One person postponing vaccination may feel safe — until an outbreak arrives. In the real world, thousands of CVEs (security vulnerabilities) are announced every year, and attackers read those announcements at the same time you do. The time between a patch being released and you applying it is a race. In this episode we turn patching from a frightening manual ritual into an accountable, scheduled process: the PSWindowsUpdate module for single machines, WSUS for large organizations, and Get-Hotfix for verification.

The Patching Cycle and Why Automate

There are three reasons manual patching fails in production:

  1. Consistency. Scripts apply the same patch to all machines. Humans forget, delay, or click the wrong button.
  2. Audit. Scripts record what was installed and when. Management asks "which servers are patched this month?" — the answer is in the logs, not in memory.
  3. Speed. Emergency patches (zero-day) must be applied within hours, not weeks. A ready script can run once for 100 servers.

The best industry pattern is the maintenance window: a fixed schedule, for example Sunday at 02:00, when a script runs automatically, installs patches, restarts if needed, and writes a report.

PSWindowsUpdate: Automation for a Single Machine

Windows Update on modern Windows 10/11 is already fairly automatic. But for servers, machines without update policies, or full control over the process, the community module PSWindowsUpdate is the right tool. Its cmdlets mirror the original Windows Update names: Get-WindowsUpdate, Install-WindowsUpdate, Get-WUHistory, and others.

Installing the Module

PSWindowsUpdate is available on the PowerShell Gallery. Because this module writes to the system, run the console as Administrator:

Installing the PSWindowsUpdate module
Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
Install-Module -Name PSWindowsUpdate -Scope CurrentUser -Force
Import-Module PSWindowsUpdate
 
Get-Command -Module PSWindowsUpdate | Select-Object Name

Viewing Available Updates

Get-WindowsUpdate shows updates not yet installed on this machine. Add -MicrosoftUpdate to include Microsoft Office and other product updates, not just Windows:

Displaying available updates
Get-WindowsUpdate -MicrosoftUpdate | Select-Object Title, Status, Size, KB

Note the KB column — the Knowledge Base number (for example KB5050021) we'll use for verification and rollback later.

Installing Updates

Install-WindowsUpdate downloads and installs, with -AcceptAll to accept all licenses and -AutoReboot for automatic restart if needed:

Installing all updates
Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -AutoReboot

Important

-AutoReboot will restart the machine without waiting. On production servers, never run this command outside a maintenance window. The safe pattern: run without -AutoReboot, check -RebootRequired afterward, and let the scheduling decide when the restart happens.

Approval and Scheduling

For full control, combine Install-WindowsUpdate with Task Scheduler. First, save the patching script:

update-windows.ps1 — patching script
# update-windows.ps1
Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -AutoReboot -ErrorAction Continue

Then register it as a weekly scheduled task:

Registering a patching scheduled task
$action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File C:\Scripts\update-windows.ps1"
$trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Sunday -At 02:00
$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest
 
Register-ScheduledTask -TaskName "Patch-Mingguan" `
    -Action $action -Trigger $trigger -Principal $principal -Force

The task runs as SYSTEM — the account with the highest rights on the machine — so no passwords need to be stored in the script. Register-ScheduledTask is the standard way to schedule PowerShell scripts on Windows.

WSUS Integration for Large Organizations

For dozens or hundreds of machines, WSUS (Windows Server Update Services) is the answer: a server that downloads patches once then distributes them to all client machines. The benefits: saved bandwidth, full control over approved patches, and a single management point.

The WSUS module is bundled with the WSUS role on Windows Server. The main cmdlets an administrator needs:

Viewing the WSUS server and unapproved updates
$wsus = Get-WsusServer -Name "wsus01.corp.local" -PortNumber 8530
 
Get-WsusUpdate -UpdateServer $wsus -Approval Unapproved |
    Select-Object Title, UpdateClassification, UpdateRevisionNumber

Get-WsusUpdate fetches the update list from the WSUS server. The -Approval Unapproved filter shows patches already downloaded to WSUS but not yet approved — this is the "decision pile" you must manage.

Approving Updates

Approve-WsusUpdate applies the decision: this patch may be installed by all clients (or specific targets):

Approving unapproved updates
$wsus = Get-WsusServer -Name "wsus01.corp.local" -PortNumber 8530
$updates = Get-WsusUpdate -UpdateServer $wsus -Approval Unapproved
 
Approve-WsusUpdate -Update $updates -Action Install -UpdateServer $wsus

-Action Install means the update is approved for installation; another option like -Action Remove is for declining. Once approved, clients fetch and install it according to their schedule.

Reporting

Compliance reports are management meeting material. From the server side:

Update status report from WSUS
$wsus = Get-WsusServer -Name "wsus01.corp.local" -PortNumber 8530
 
Get-WsusUpdate -UpdateServer $wsus -Approval Approved |
    Select-Object Title, UpdateClassification, ApprovedDate |
    Export-Csv -Path "C:\Data\wsus-approved.csv" -NoTypeInformation -Encoding UTF8

Update History and Verification

Get-Hotfix

Get-Hotfix reads the installed update history directly from WMI. This is the fastest verification tool and requires no additional modules:

Installed update history
Get-HotFix | Sort-Object InstalledOn -Descending |
    Select-Object -First 10 HotFixID, Description, InstalledOn, InstalledBy
 
Get-HotFix -Id KB5050021

The second command verifies a specific patch: if there's no output, that patch isn't installed on this machine.

Verification and Rollback

A common verification pattern: check for the patch's presence before and after the patching process. If Get-Hotfix -Id KB5050021 fails (patch absent), the patching process wasn't complete.

If a patch turns out to break the system, rollback is done via wusa (Windows Update Standalone Installer):

Removing (rolling back) a patch
wusa.exe /uninstall /kb:5050021 /quiet /norestart

Warning

Patch rollback is a last-resort emergency operation, not normal flow. Some patches can't be removed, and removing a security patch reopens the vulnerability. The correct order: identify the problematic patch via Get-Hotfix, check whether it was recently installed, then decide whether rollback is better than fixing the impact. Never do a "blanket" rollback without testing.

Best Practices

  1. Apply patches in waves. Don't patch all machines at once. Start with non-critical servers (test first), then production servers gradually. This limits the blast radius if a patch is problematic.
  2. Hold to the patch calendar. Microsoft releases patches on "Patch Tuesday" (the second Tuesday of each month). Schedule your testing window Wednesday–Thursday and production application on the weekend.
  3. Verify each wave. After patching, run Get-Hotfix, check system logs for errors, and confirm core services are still alive before moving to the next wave.
  4. Create automated reports. Combine Get-Hotfix and Export-Csv into a monthly compliance script — management loves numbers, and audits will ask for them.
  5. Store patching scripts in a repository. Version the scripts, review them like regular code, and push them through a CI/CD pipeline as we'll discuss in the series' final episodes.

Conclusion

In this episode 20 you've turned patching from a manual ritual into a schedulable, accountable process: the PSWindowsUpdate module with Install-Module PSWindowsUpdate, Get-WindowsUpdate, and Install-WindowsUpdate -AcceptAll -AutoReboot; scheduling via Task Scheduler; WSUS integration with Get-WsusUpdate and Approve-WsusUpdate for large organizations; update history and verification via Get-Hotfix; and rollback with wusa.

Key takeaways:

  • Delayed patches are a security risk — schedule them, don't wait for an incident.
  • Install-WindowsUpdate with -AutoReboot must only run in a maintenance window.
  • Use WSUS for medium-large scale; Get-WsusUpdate and Approve-WsusUpdate are the heart of the operation.
  • Verify with Get-Hotfix, and keep rollback via wusa as a last-resort option.

Your machines are now always current and secure. The next question: how do you make sure the machine is properly connected to the network? In the next episode, episode 21, we'll cover Network Configuration: managing adapters with Get-NetAdapter and Set-NetAdapter, static and DHCP IP configuration, DNS client settings, and troubleshooting with Test-Connection, Test-NetConnection, and Resolve-DnsName. See you there!

Learn PowerShell - Windows Updates & Patching | Learn PowerShell