If you go check the PowerShell Gallery you will find a great module in the top 100 downloads called PSWindowsUpdate. This is one of my favorite modules because it fits a specific need that many organizations have, which is orchestrating the deployment of Windows updates. There are many great cmdlets in this module, but the one I will focus on today is Invoke-WUInstall, used to install Windows updates remotely.
Installing PSWindowsUpdate
Since PSWindowsUpdate is not installed on Windows by default, we have to first install the module. Luckily, we can do this easily from the PowerShell Gallery. Note I am using an older version from July 2017 (1.5.2.6).
PS C:\WINDOWS\system32> Install-Module PSWindowsUpdate -MaximumVersion 1.5.2.6
If we run Get-Command we can see all of the commands in the PSWindowsUpdate module:
PS C:\WINDOWS\system32> Get-Command -Module PSWindowsUpdate
CommandType Name Version Source
----------- ---- ------- ------
Alias Get-WindowsUpdate 1.5.2.6 pswindowsupdate
Alias Hide-WindowsUpdate 1.5.2.6 pswindowsupdate
Alias Install-WindowsUpdate 1.5.2.6 pswindowsupdate
Alias Uninstall-WindowsUpdate 1.5.2.6 pswindowsupdate
Function Add-WUOfflineSync 1.5.2.6 pswindowsupdate
Function Add-WUServiceManager 1.5.2.6 pswindowsupdate
Function Get-WUHistory 1.5.2.6 pswindowsupdate
Function Get-WUInstall 1.5.2.6 pswindowsupdate
Function Get-WUInstallerStatus 1.5.2.6 pswindowsupdate
Function Get-WUList 1.5.2.6 pswindowsupdate
Function Get-WURebootStatus 1.5.2.6 pswindowsupdate
Function Get-WUServiceManager 1.5.2.6 pswindowsupdate
Function Get-WUUninstall 1.5.2.6 pswindowsupdate
Function Hide-WUUpdate 1.5.2.6 pswindowsupdate
Function Invoke-WUInstall 1.5.2.6 pswindowsupdate
Function Remove-WUOfflineSync 1.5.2.6 pswindowsupdate
Function Remove-WUServiceManager 1.5.2.6 pswindowsupdate
How Invoke-WUInstall works
One different aspect of using Invoke-WUInstall is that it does not use traditional PowerShell remoting methods to perform Windows update installs. When you look at the source code, it actually creates and immediately runs a scheduled task on the remote machine under the SYSTEM account.
Write-Verbose "Create schedule service object"
$Scheduler = New-Object -ComObject Schedule.Service
$Task = $Scheduler.NewTask(0)
$RegistrationInfo = $Task.RegistrationInfo
$RegistrationInfo.Description = $TaskName
$RegistrationInfo.Author = $User.Name
$Settings = $Task.Settings
$Settings.Enabled = $True
$Settings.StartWhenAvailable = $True
$Settings.Hidden = $False
$Action = $Task.Actions.Create(0)
$Action.Path = "powershell"
$Action.Arguments = "-Command $Script"
$Task.Principal.RunLevel = 1
A typical use of Invoke-WUInstall would be:
Invoke-WUInstall -ComputerName Test-1 -Script {ipmo PSWindowsUpdate; Get-WUInstall -AcceptAll | Out-File C:\PSWindowsUpdate.log }
In this command we see Get-WUInstall, which is the command PSWindowsUpdate uses to install updates, usually from your Windows Server Update Services (WSUS) server. Get-WUInstall simply uses a COM object for Windows updates to perform the tasks needed. Notice also the use of the -AcceptAll parameter, which means it will automatically accept any updates to install.
One nice feature of Invoke-WUInstall is that it actually installs the PSWindowsUpdate module on the remote machine (if it isn't there already). This is great when you are using the module on a new machine, or when you decide to use it for the first time.
C:\ > $cim = New-CimSession -ComputerName Test-1
InstanceId : afa8c63d-fb1f-46f9-8082-c66238750a92
C:\Scripts\PowerShell> (Get-ScheduledTask -TaskPath "\" -CimSession $cim -TaskName PSWindowsUpdate).actions
Arguments : -Command ipmo PSWindowsUpdate; Get-WUInstall -AcceptAll -AutoReboot | Out-File C:\PSWindowsUpdate.log
As you can see, the scheduled task is going to run ipmo PSWindowsUpdate; Get-WUInstall -AcceptAll -AutoReboot | Out-File C:\PSWindowsUpdate.log. Using Out-File will ensure the logs of downloading and installing updates are visible so we can check against them later.
Install updates on multiple machines
The true power of Invoke-WUInstall is when you have to install updates on many machines at once. This is very easy to do, all you need is to add machines to the ‑ComputerName parameter, which then processes them in a loop (not in parallel unfortunately).
C:\ > Invoke-WUInstall -ComputerName Test-1,Test-2,Test-3,Test-4 -Script {ipmo PSWindowsUpdate; Get-WUInstall -AcceptAll | Out-File C:\
PSWindowsUpdate.log } -Confirm:$false -Verbose
VERBOSE: Populating RepositorySourceLocation property for module PSWindowsUpdate.
VERBOSE: Loading module from path 'C:\Program Files\WindowsPowerShell\Modules\PSWindowsUpdate\1.5.2.6\PSWindowsUpdate.psm1'.
VERBOSE: Create schedule service object
VERBOSE: Performing the operation "Invoke WUInstall" on target "Test-1".
Finding errors
One great reason to output to a log on the remote machine is to confirm that no errors installing updates on these remote machines occurred. With some simple PowerShell, we can query these log files and search for failures.
Here is what a typical log looks like after using Get-WUInstall -AcceptAll | Out-File C:\ PSWindowsUpdate.log:
Invoke WUInstall log
It includes the status of the update, its KB number, size, and title—all great information to have handy when installing updates.
Using Invoke-Command, Get-Item, and Select-String, we can use a quick technique to easily work through any computers used with Invoke-WUInstall and find Windows updates that failed to install:
C:\> Invoke-Command -ComputerName Test-1,Test-2,Test-3 -ScriptBlock {
>> Get-Item C:\PSWindowsUpdate.log | Select-String -Pattern "failed" -SimpleMatch |
>> Select-Object -Property line } | Select-Object -Property Line,PSComputerName
4 Failed KB4103712 30 MB 2018-05 Security Only Quality Update for Windo... Test-1
Conclusion
While there are other solutions for managing Windows update deployment, PSWindowsUpdate provides a Windows admin a free and very powerful tool to manage updates. With some simple PowerShell scripting, an admin can orchestrate updates across the enterprise in conjunction with WSUS as well.
Original page