Preface
Most of my Windows servers are patched by WSUS, SCCM or a similar automated patch management solution at regular intervals. But not all. Some servers are just too important to be autopatched. This is a combination of SLA requirements making downtime difficult to schedule and the sheer impact of a botched patch run on backend servers. Thus, a more hands-on approach is needed. In W2012R2 and far back this was easily achieved by running the manual Windows Update application. I ran through the process in QA, let it simmer for a while and went on to repeat the process in production if no nefarious effects were found during testing. Some systems even have three or more staging levels. It is a very manual process, but it works, and as we are required to hand-hold the servers during the update anyway, it does not really cost anything. Then along came Windows Server 2016. Or Windows 10 I should really say, as the Update-module in W2016 is carbon copied from W10 without changes. It is even trying to convince me to install W10 Creators update on my servers…
In Windows Server 2016 the lazy bastards at Microsoft just could not be bothered to implement the functionality from W2012R2 WU. It is no longer possible to defer specific updates I do not want, such as the stupid Silverlight mess. If I want Microsoft update, then I have to take it all. And if I should become slightly insane and suddenly decide I want driver updates from WU, the only way to do that is to go through device manager and check every single device for updates. Or install WUMT, a shady custom WU client of unknown origin.
I could of course use WSUS or SCCM to push just the updates I want, but then I have to magically imagine what updates each server wants and add them to an ever growing number of target groups. Every time I have a patch run. Now that is expensive. If I had enough of the “special needs” servers to justify the manpower-cost, I would have done so long ago. Thus, another solution was needed…
PSWindowsUpdate to the rescue. PSWindUpdate is a Powershell module written by a user called MichalGajda on the technet gallery enabling management of Windows Update through Powershell. In this post I go through how to install the module and use it to run Microsoft Update in a way that resembles the functionality from W2012R2. You could tell the module to install a certain list of updates, but I found it easier to hide the unwanted updates. It also ensures that they are not added by mistake with the next round of patches.
Getting started
(See the following chapters for details.)
- You should of course start by installing the module. This should be a one-time deal, unless a new version has been released since last time you used it. New versions of the module should of course be tested in QA like any other software.
- Then, make sure that Microsoft Update is active.
- Check for updates to get a list of available patches.
- Hide any unwanted patches
- Install the updates
- Re-check for updates to make sure there are no “round-two” patches to install.
Installing the module
- Download from https://gallery.technet.microsoft.com/scriptcenter/2d191bcd-3308-4edd-9de2-88dff796b0bc
- Copy the folder in the ZIP-file into %WINDIR%\System32\WindowsPowerShell\v1.0\Modules
- Run this command from an administrative Powershell window:
Add-Content $Env:WINDIR\system32\WindowsPowerShell\v1.0\profile.ps1 "`nImport-Module PSWindowsUpdate"
Deploying the module remotely
You can run this from a computer that already has the PSWindowsUpdate module installed to deploy PSWindowsUpdate.
$Targets = "Computer1", "Computer2"
Update-WUModule -LocalPSWUSource "C:\Windows\system32\WindowsPowerShell\v1.0\Modules\PSWindowsUpdate" -ComputerName $Targets
Invoke-Command -ComputerName $Targets -ScriptBlock{ Add-Content $Env:WINDIR\system32\WindowsPowerShell\v1.0\profile.ps1 "`nImport-Module PSWindowsUpdate"}
Make sure Microsoft Update is enabled
Get-WUServiceManager
If it is not enabled and set as default, run this command:
Add-WUServiceManager -ServiceID "7971f918-a847-4430-9279-4a52d1efe18d" -AddServiceFlag 7
API ref: https://msdn.microsoft.com/en-us/library/windows/desktop/bb394819(v=vs.85).aspx
Check for updates from Microsoft Update
List the available updates from Microsoft Update
Get-WUList -MicrosoftUpdate
Filter out all driver updates:
Get-WUList -MicrosoftUpdate -NotCategory "Drivers"
Hide unwanted updates
Hides the update and makes sure we do not install unwanted things like hat pesky Silverlight stuff.
Add the KB IDs you want to hide to the array, and run HideWuUpdate against that array:
$HideList = "KB4013867", "KB890830"
Hide-WUUpdate -KBArticleID $HideList
Note: KB890830 is listed twice because it has been published twice with different names. When this happens, one of the KBs will fail to install.
List hidden updates
Get-WUList -IsHidden
Un-hide previously hidden updates
Let us say that you did not really want to hide the Malicious Software Removal KB from the hide-example. No problem, just run the command again with the -Hidestatus:$false option:
$HideList = "KB890830"
Hide-WUUpdate -KBArticleID $HideList -HideStatus:$false
Install updates
When you have hidden any updates you do not want to install, just run this command:
Get-WUInstall -MicrosoftUpdate -AcceptAll
The X shows the progress. Step 4 is finished. If you want to reboot automatically, add -AutoReboot. Otherwise you will be presented with a reboot-prompt as shown in the example.
If a reboot is required prior to installation, installation will be halted with a message prompting you to reboot the server.
Again, you can filter drivers or any other category of updates with the –NotCategory option.
2 thoughts on “Microsoft Update with PSWindowsUpdate”