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 }
-Confirm:$false –Verbose

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
C:\ > $cim

Id           : 2
Name         : CimSession2
InstanceId   : afa8c63d-fb1f-46f9-8082-c66238750a92
ComputerName : Test-1
Protocol     : WSMAN

C:\Scripts\PowerShell> (Get-ScheduledTask -TaskPath "\" -CimSession $cim -TaskName PSWindowsUpdate).actions
Id               :
Arguments        : -Command ipmo PSWindowsUpdate; Get-WUInstall  -AcceptAll -AutoReboot | Out-File C:\PSWindowsUpdate.log
Execute          : powershell
WorkingDirectory :
PSComputerName   : Test-1

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

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:

Subscribe to 4sysops newsletter!

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
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.

avataravatar
40 Comments
  1. geert 4 years ago

    I don’t have the Invoke-WUInstall cmd

    • Author
      Dan Franciscus 4 years ago

      Sorry should have specified this. Its not a builtin PowerShell module.

      https://www.powershellgallery.com/packages/PSWindowsUpdate/2.0.0.4

      Install by doing:

      Install-Module PSWindowsUpdate

      • Caleb 4 years ago

        I just installed this module, and the “Invoke-WUInstall’ cmdlet is not available.

        • Author
          Dan Franciscus 4 years ago

          Sorry its in version 1 it seems. I never realized major changes were made to newer versions.

          avatar
        • Shawn 2 years ago

          They changed the name of the command from  Invoke-WUInstall        => Invoke-WUJob

    • Adam 3 years ago

      The newer version 2.1.1.2 doesn't utilize the Invoke-WUInstall.

      I believe the cmdlet Get-WindowsUpdate is the switch to use I believe. I am looking into this to see about making it work for me as well.

  2. Jimmy 4 years ago

    I also don’t have this cmdlet on my PS. But i found this one: Install-WUUpdates, wight does the same thing?

  3. Paolo Frigo 4 years ago

    Maybe I’m wrong but I think the cmd-let is included on Michael Gajda’s
    Windows Update PowerShell Module

     

  4. James 4 years ago

    You can’t see the source code anymore since version 2.0. It also is significantly slower. Has anyone had any luck getting in contact with Michael Gadja the creator?

    • Author
      Dan Franciscus 4 years ago

      Darn thats a shame. I couldnt find it on Github. Maybe he is going to try and sell it lol.

  5. Caleb 4 years ago

    The Invoke-WUInstall was removed from this module starting with version 2.0.0.0 last October.

    avatar
    • Author
      Dan Franciscus 4 years ago

      Yep, I am going to update the article specifying I was using an older version.

      avatar
      • Luc Fullenwarth 4 years ago

        I discovered the new version a few weeks ago and there are some breaking changes but also new interesting cmdlets.

  6. Jimmy 4 years ago

    So PS cmdlet on above article works only if you have the old version?

    There is no other way of doing this? Because this could be very handy for me.

    • Caleb 4 years ago

      @Jimmy, I believe this is how you run the command on the newer version:

      Invoke-WUJob -Script "ipmo PSWindowsUpdate; Install-WindowsUpdate -AcceptAll | Out-File C:\PSWindowsUpdate.log" -TriggerDate (Get-Date -Hour 18 -Minute 0 -Second 0)
      

      That command would run the updates at 6:00pm today.

  7. Octavio 4 years ago

    I think this wont work in 2016 server, does it?

  8. Stiven Castro 4 years ago

    Hi

    Does anyone knows if this works on Azure VM’s?

     

    • Luc Fullenwarth 4 years ago

      @Stiven Castro

      Yes it works also on Azure VMs.

      If you want to run it locally, just install the module.

      If you want to run it remotely you have to open the remoting ports and also ensure your local account is an administrator of the remove VM.

  9. nanodroid 3 years ago

    Running this command on a 2016 server it seems to complete but no updates are accually installed, does this work for 2016 server or is there a different command for it.

     

    Invoke-Command -ComputerName server2016 -Script {ipmo PSWindowsUpdate; Get-WUInstall -AcceptAll | Out-File C:\PSWindowsUpdate.log }

     

    • Luc Fullenwarth 3 years ago

      @nanodroid

      The Get-WUInstall is misleading because the cmdlet only lists updates. You must use the -Install parameter in order to effectively install updates.

  10. Chandan 3 years ago

    is there any option to get system restart notification if restart is required during windows update ?

  11. Antonio 3 years ago

    You've mentioned, this Module will actually install the module on the remote server if its missing – but how? Will it use the local resources?

    Does that mean, that all servers must have internet connectivity? If yes – how can I implement it without internet connection?

  12. Andreas 3 years ago

    I want to use this script to remotely install ONLY a particular update. The latest Windows feature version(1903 today). I don't want to start an all out update of all the latest updates on the remote computer, just the 1903 feature update. How can i use this script to achieve that?

    • Jonathan Baynes 3 years ago

      Diddo. I somehow doubt it. I've not found a good way to do this without system center. I have lots of remotely managed devices. I'm a small MSP, and I've not found a good way to push 1903 out yet. Anyone have a comment on that? 

       

      Only think i have seen is downloaded the iso, extracting it to a folder, and then I'd have to push that entire folder out and could run a command to force the update. But it would be much better if a powershell command could initiate the process including the download from Microsoft. 

      • Ben 3 years ago

        I use PDQ in my company using an extracted ISO, I copy the files locally (but you could probably run from a network location too).

        I use the command line:

        start /wait c:\UpgradeInstall\1809\setup.exe /auto upgrade /Compat IgnoreWarning /installfrom c:\UpgradeInstall\1809\sources\install.wim /dynamicupdate enable /showoobe none /quiet

        We use this method because we have issues with windows index/windows search corruption and have to stop the service before the update – probably because we have gpo-restricted cortana/windows search significantly.

  13. uminds 3 years ago

    I am trying to install update remotely on a Windows 2016 server and it wasn't success. I used the following cmdlet.

    pswindowsupdate 2.0 is installed locally on the server

    invoke-wujob -comp server1 -runnow -cred $(get-credential) -script {get-windowsupdate -install -acceptall}

    It always said access denied. The account I used is domain admin. I am however able to use invoke-command and run the scriptblock get-windows update. What other permission I need for this?

    Thanks

  14. Piyush Pandya 3 years ago

    Where you mention, that PSWindowsUpdate will install on the remote server if it is not there, does the remote server need Internet access to install PSWindowsUpdate?  Or does it take from an internal location? Can we specify a location?

  15. Jennie 3 years ago

    You might want to include the following commands:

    Set-ExecutionPolicy RemoteSigned

    This allows you to run the script on the comptuer

    Import-Module PSWindowsUpdate

    This imports the module so you can use it

    If the PC doesn't have internet access, you can copy the PSWindowsUpdate folder from C:\Windows\System32\WindowsPowerShell\v1.0 folder from a computer with internet to the same folder on the non-internet computer. Then run:

    Set-ExecutionPolicy RemoteSigned
    Import-Module PSWindowsUpdate

  16. John Harrison Midkiff 3 years ago

    Just ran across this.  I am trying the below command but always get prompted for "RunNow" parameter.  What his that?

     

    Invoke-WUJob -ComputerName COMPUTER -Script "ipmo PSWindowsUpdate; Install-WindowsUpdate -AcceptAll | Out-File C:\PSWindowsUpdate.log"

  17. Gil 3 years ago

    To see the examples, type: "get-help Invoke-WUJob -examples"

  18. mark 2 years ago

    How does one get this to work with no wifi or Bluetooth chip in the machine?

    • Paolo Maffezzoli 2 years ago

      You can update a computer without an Internet connection with third party tools like WSUS Offline Update.

  19. pedja 2 years ago

    This script work !!!

    Invoke-WUInstall -ComputerName comp1 -Script {ipmo PSWindowsUpdate; Set-ExecutionPolicy Bypass -Scope Process -Force ; Import-Module PSWindowsUpdate; Get-WUInstall -AcceptAll | Out-File C:\pswu.log } -Confirm:$false –Verbose

    • David 1 year ago

      How did you get an "Invoke-WUInstall" command?

      • Leos Marek 1 year ago

        You need to get the proper module. Its described in the article! 🙂

  20. Tyler 1 year ago

    I keep getting an error when trying to send the update to a single computer or variable created.

    [Invoke-WUJob -ComputerName TRJWIN10-9 -Script {ipmo PSWindowsUpdate; Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -AutoReboot} -RunNow -Confirm:$false]

    It then prompts a RunNow:, so I put $true. 

    Then gives me the error: Invoke-WUJob : cannot convert 'system.string' to the type 'system.management.automation.switchparameter' required by parameter 'RunNow'. 

    I have enabled PSRemoting on client and PC I am using, setting Execution-Policy to Unrestricted, and setting a list of trusted hosts.

    Any tips?

    Thank you!

  21. Dave 11 months ago

    This script works for 2012 and 2016 servers. I found they can not run the same command.
    Create a text file with your server names, one server per line. Save this as a script and run that, it will create task on each server to run immediately, but not reboot. You can adjust accordingly. Also noticed that if the folder for the log files does not exist, the script fails. The email part also works, just edit for your server and name.

    # This script will look in the test.txt file for server names
    # Then install Missing Windows Updates 
    Clear
    $a = new-object -comobject wscript.shell
    $b = $a.popup("Do you want to Install Windows Updates on all Test Servers now?",0,"Updates",32+4)
    If($b -eq 7){Exit}
    
    $YourFile = Get-Content 'c:\Scripts\test.txt'
    
    foreach ($computer in $YourFile){
    	$OSInfo = (Get-WmiObject Win32_OperatingSystem -ComputerName $Computer).Version
    
    If ([version]$OSInfo -gt "10.0.1")
    {
    invoke-WUJob -ComputerName $computer -Script {Import-Module PSWindowsUpdate ; Set-ExecutionPolicy Bypass -Scope Process -Force ; Install-WindowsUpdate -AcceptAll -SendReport -IgnoreReboot -PSWUSettings @{SmtpServer='XX';From='wsus@XX';To='XXX';Port=25} | Out-File C:\bginfo\PSWindowsUpdateLog2016.txt -Append} -Confirm:$false -RunNow -Verbose
    }
    Else
    {
    invoke-WUJob -ComputerName $computer -Script { Import-Module PSWindowsUpdate ; Install-WindowsUpdate -AcceptAll -SendReport -IgnoreReboot -PSWUSettings @{SmtpServer='XXXX';From='wsus@XXX';To='XXXX';Port=25} | Out-File C:\bginfo\PSWindowsUpdateLog2012.txt -Append} -Confirm:$false -RunNow -Verbose
    }
    }
    
    

Leave a reply

Your email address will not be published.

*

© 4sysops 2006 - 2022

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account