icetray - Fotolia

How to automate patch management in Windows

Automating Windows updates with PowerShell will ease some of the labor associated with the routine patch deployment process.

Patch Tuesday comes every month like clockwork for IT administrators. For routine jobs such as patch management in Windows, it's essential to use automation to make this chore more tolerable.

There are many products to help you deploy Windows patches to your systems, but they're usually expensive. If you can't afford these offerings, another option is to roll your own automated Windows patching routine. Using PowerShell, IT teams can test, deploy and verify Windows updates across hundreds of machines using nothing but some PowerShell kung fu and some prebuilt modules.

Prerequisites for automated patch management in Windows

To follow along, you should have the following prerequisites set up:

  • Windows PowerShell 5.1 on a client;
  • PowerShell remoting available on the remote systems to patch;
  • logged in or have access to an account with local administrator permissions on the remote systems;
  • an Active Directory environment;
  • the Active Directory PowerShell module on your client; and
  • a Windows Server Update Services (WSUS) server installed and set up to manage your systems.

Set up a test environment

As most administrators know, you never push out patches directly to your production systems, which means you need to set up a test environment. You should configure this with a sampling of the operating systems and configurations of all systems that receive patches.

To determine what you have in your inventory, use the following script. It queries all Active Directory computers in the domain and groups them by the operating system.

$computerCount = 2
$properties = @( 
    @{Name='OperatingSystem';Expression={$_.Name}},
    @{Name='TotalCount';Expression={$_.Group.Count}},
    @{Name='TestComputers';Expression={$_.Group | Select-Object -ExpandProperty Name -First $computerCount }} 
) 
$testGroups = Get-ADComputer -Filter * -Properties OperatingSystem | Group-Object -Property OperatingSystem | Select-Object -Property $properties $testGroups

When the script runs, it groups the output by the type of machines and how many there are.

OperatingSystem                TotalCount TestComputers
---------------                ---------- -------------
Windows Server 2016 Datacenter          3 {SRDC01, SCRIPTRUNNER01}

Now that you know what operating systems you have, you can either convert the physical machines to virtual ones or perhaps build new virtual machines in your hypervisor of choice. You can do that with PowerShell, but that is outside of the scope of this article. This tutorial will continue on the assumption you executed the conversion and are ready to proceed.

Deploying Windows updates

Once you've got your test VMs set up, check to see if there are new patches available. You will need to use the WSUS server to find this information.

When you've discovered the Microsoft Knowledge Base (KB) IDs of all patches to test, you can deploy these patches using the PSWindowsUpdate module. To download and install, use this command:

Install-Module PSWindowsUpdate

Next, deploy the patches, but first, you'll need to ensure you've got the appropriate firewall port exceptions for the Windows Firewall enabled. Here's a quick PowerShell command to enable it on remote systems:

New-NetFirewallRule -DisplayName "Allow PSWindowsUpdate" -Direction Inbound -Program "%SystemRoot%\System32\dllhost.exe" -RemoteAddress Any -Action Allow -LocalPort 'RPC' -Protocol TCP

Next, you can run a quick test by running a simple command such as Get-WUHistory to see if it returns an error or if it returns a patch history. If it's the latter, then you can proceed.

Now it's time to deploy the Windows patches to the test groups. For this tutorial, deploy KB ID KB4091664. Start by copying the PSWindowsUpdate module to the remote computers, and then initiate the install. Also, schedule a reboot during the maintenance window. In this instance, that's a time two hours from now.

foreach ($computer in $testGroups.TestComputers) {
    Copy-Item -Path "$Env:PROGRAMFILES\WindowsPowerShell\Modules\PSWindowsUpdate" -Destination "\\$computer\c$\Program Files\WindowsPowerShell\Modules" -Recurse
    Install-WindowsUpdate -ComputerName $computer -KBArticleIds 'KB4091664' -Schedule (Get-Date).AddHours(2)
}

X ComputerName Result     KB          Size Title
- ------------ ------     --          ---- -----
1 scriptrun... Accepted   KB4091664    1MB 2018-09 Update for Windows Server 2016 for x64-based Systems (KB4091664)

This script starts the patch installation on each computer. To monitor the progress, you can use the Get-WUHistory command.

Get-WUHistory -ComputerName scriptrunner01 -Last 1
ComputerName Operationname  Result     Date                Title
------------ -------------  ------     ----                -----
scriptrun... Installation   InProgress 4/4/2019 9:31:21 PM 2018-09 Update for Windows Server 2016 for x64-based Systems (KB4091664)

Dive deeper into the PSWindowsUpdate module

This article just covers the basics of rolling out an automated way to handle patch management in Windows with PowerShell. PSWindowsUpdate is a great time-saver with extensive functionality. It's worth investigating the help in this PowerShell module to see how you can customize it based on your needs.

Dig Deeper on Windows Server OS and management

Cloud Computing
Enterprise Desktop
Virtual Desktop
Close