Automating Windows updates using the PowerShell PSWindowsUpdate module
I will admit it. I love PowerShell and if my choice is to use PowerShell over another tool to do just about anything, I am choosing PowerShell even if it may not be the “best” tool for the job. The PowerShell community is getting larger and larger as great developers are adding quality modules to PSGallery, but perhaps my favorite module so far is PSWindowsUpdate. This is a module created by Michal Gajda and is one of the most popular modules (222k downloads).
There are only two cmdlets I use for the most part with PSWindowsUpdate, Invoke-WUInstall along with Get-WUInstall. Invoke-WUInstall allows you to kick off the installation of patches remotely and it works beautifully.Get-WUInstall actually downloads and installs the updates. To install all available updates and reboot when finished you can run Get-WUInstall -AcceptAll -AutoReboot locally.
A look inside the Get-WUInstall code and you will see the remoting is actually done via the task scheduler. A scheduled task is created and runs on the remote computer under the system account due to certain methods not available with PowerShell remoting (pretty cool way to get around this). The scheduled task is a PowerShell command that you specify. In my case I use Invoke-WUInstall -ComputerName <ComputerName> -Script {ipmo PSWindowsUpdate; Get-WUInstall -AcceptAll -AutoReboot | Out-File C:PSWindowsUpdate.log } -Confirm:$false -Verbose. This allows me to start the update process on remote machines and log the output. One drawback for Invoke-WUInstall is that it does not monitor the output of the update process after you run it. A workaround I use for this is adding a few lines to Get-WUInstall to send an email to me when the computer is finished installing updates. The email includes which updates were installed and if they were successful or not. In this example I want to install updates on all servers in my “Servers” OU in my Active Directory domain at the same time:
Invoke-WUInstall -ComputerName (Get-ADComputer -Filter 'Operatingsystem -like "*Windows Server*"' -SearchBase "OU=Servers,DC=DOMAIN,DC=COM" | Select-Object -ExpandProperty Name) -Script {ipmo PSWindowsUpdate; Get-WUInstall -AcceptAll -AutoReboot | Out-File C:\PSWindowsUpdate.log } -Confirm:$false -Verbose
A VERY dangerous script to run on all systems and auto-reboot.
It would be best to not try this script but learn how to pull groups from AD containers and run. Of course, unfortunately over the 21 years I have worked in IT, the majority of AD structures I have seen have been set to only make use of user object security hierarchy, leaving the computer objects all in the root Computers container for the domain. ONLY a very few businesses ever actually managed computer objects, like domain controllers, mainly Labs managing computers by security filtering. But the objects themselves still reside in the defaulted folders.
I say all that to say running against Computer objects from AD will likely hit every server and system in the entire domain all at once. That’s just a bad idea.
WSUS of course manages things a bit more wisely.
If you are going to run scripts do it in small groups and be careful. One bad slip in your syntax and you are fired.
Yeah, this is a bad example I suppose. I will change that to point to a specific OU instead. Obviously you would not want to reboot domain controllers along with other servers. If you are saying to use GPOs/WSUS to manage scheduling server updates and reboots though, I do not agree with that. You can manage that with PowerShell better and easier IMO. In medium/large environments you probably want to reboot servers in a certain order and see if any failed, etc.