PSWindowsUpdate Packages

Purpose:

You are looking for a WSUS/Microsoft Update replacement integrated with PDQ Products to ensure that endpoints have all available patches from Microsoft.

Overview:

Although we currently offer Microsoft Cumulative Updates in our Package Library, we frequently have customers asking about a full WSUS/Microsoft Update replacement integrated into our products. While we typically avoid third-party tools, the PSWindowsUpdate module is well-known and widely used for checking and applying all available Microsoft updates to a machine and can be a viable alternative to WSUS/Microsoft Update. This is also an advantage for Connect customers, having the Microsoft Updates downloaded directly from Microsoft servers instead of a traditional on-premise server. 

If you are a military or government organization, you may want to review this PowerShell Module in greater detail before placing it into production to ensure that it meets your security standards:

Publisher: PowerShellGallery

Download: PSWindowsUpdate

VirusTotal: Report

Requirements:

1. Endpoints must have internet access. These packages will not work on air-gapped networks.

2. PowerShell scripts must be enabled and allowed to run on endpoints.

3. Endpoints must have access to Microsoft servers to download updates.

Getting Started:

There are currently 6 Packages in the Package Library available for you to use:

1. PSWindowsUpdate - Get All Applicable Updates from Microsoft (Audit Only)

2. PSWindowsUpdate - Install All Applicable Updates from Microsoft (No Drivers, No Feature Updates)

3. PSWindowsUpdate - Install All Applicable Critical and Security Updates from Microsoft

4. PSWindowsUpdate - Install All Applicable Drivers from Microsoft

5. PSWindowsUpdate - Install All Applicable Feature Updates from Microsoft

6. PSWindowsUpdate - Install Specific Microsoft KB

Each of these packages will do the following:

1. Check if the PSWindowsUpdate module is installed. If it is not, it will download the Nuget Installer and then download the PSWindowsUpdate module.

2. It will then Run the PSWindowsUpdate module and check for all available Microsoft patches.

3. Depending on the package, it will then install specific updates.

4. Reboots are disabled, but may be required in order to complete the installation of some patches.

PACKAGE: Get All Applicable Updates from Microsoft (Audit Only)

This package is an Audit-Only package. You can run this and then view the Output log to see what applicable Microsoft Updates are available for the endpoint. You can then choose which other PSWindowsUpdate packages to use to install a subset or all of the updates on the machine.

PACKAGE: Install All Applicable Updates from Microsoft (No Drivers, No Feature Updates)

This package will install ALL applicable updates from Microsoft, but will not install hardware drivers or feature updates.

PACKAGE: Install All Applicable Critical and Security Updates from Microsoft

This package will install Critical and Security Patches ONLY. This package will install cumulative updates as well as other critical updates and security updates.

PACKAGE: Install All Applicable Drivers from Microsoft

There are many hardware drivers now available from Microsoft to update, including but not limited to printers, video, mice, keyboards, network, and third-party firmware drivers. We strongly recommend additional testing, especially with network and firmware drivers on test machines or a test lab before deploying to remote machines and risking OS or network connectivity issues with installation failure.

PACKAGE: Install All Applicable Feature Updates from Microsoft

This package will specifically install Feature Updates. Please note that Feature Updates can take quite a bit of time to download and install, so you may need additional contact with end users to coordinate a block of time for a feature update (overnight deployment).

PACKAGE: Install Specific Microsoft KB

This package currently is only applicable for PDQ Deploy and gives you the ability to directly modify the KB Number you wish to deploy in the Parameters field in Step 1. Please pay close attention to preserving the exact syntax in the Parameters field:

Example 1 with one KB Number:

-KBArticleID 'KB8675309'

Example 2 with 2 or more KB Numbers to install:

-KBArticleID 'KB8675309, KB9274836, KB3371337'

Customizing PSWindowsUpdate for your own Environment:

While the default packages above will be a suitable WSUS/Microsoft Update alternative for the majority of our customers, If you are comfortable with PowerShell, You can download any of the PSWindowsUpdate packages (With the exception of the Specific Microsoft KB package) and convert the auto-download package to a standard package. Then you can browse to the PowerShell file in Step 1 and there are many different options to target and install updates specifically:

General Categories:'Critical Updates', 'Definition Updates', 'Drivers', 'Feature Packs', 'Security Updates', 'Service Packs', 'Tools', 'Update Rollups', 'Updates', 'Upgrades'
Category: CategoryIDApplication: 5C9376AB-8CE6-464A-B136-22113DD69801Connectors: 434DE588-ED14-48F5-8EED-A15E09A991F6Critical Updates: E6CF1350-C01B-414D-A61F-263D14D133B4Definition Updates: E0789628-CE08-4437-BE74-2495B842F43BDeveloper Kits: E140075D-8433-45C3-AD87-E72345B36078Feature Packs: B54E7D24-7ADD-428F-8B75-90A396FA584FGuidance: 9511D615-35B2-47BB-927F-F73D8E9260BBSecurity Updates: 0FA1201D-4330-4FA8-8AE9-B877473B6441ServicePacks: 68C5B0A3-D1A6-4553-AE49-01D3A7827828Tools: B4832BD8-E735-4761-8DAF-37F882276DABUpdateRollups: 28BC880E-0592-4CBF-8F95-C79B17911D5FUpdates: CD5FFD1E-E932-4E3A-BF74-18BF0B1BBD83

Microsoft Reference

EXAMPLE: Get all available patches from Microsoft

Get-WindowsUpdate -MicrosoftUpdate -Verbose

EXAMPLE: Exclude information:

Get-WindowsUpdate -MicrosoftUpdate -Verbose -NotCategory 'Drivers' -NotTitle 'OneDrive' -NotKBArticleID 'KB4489873'

EXAMPLE: Install updates by Category

Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -Verbose -IgnoreReboot -Category 'Critical Updates', 'Security Updates', 'Updates'

EXAMPLE: Install updates by CategoryID

Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -Verbose -IgnoreReboot -CategoryIDs 'E6CF1350-C01B-414D-A61F-263D14D133B4', 'CD5FFD1E-E932-4E3A-BF74-18BF0B1BBD83', '0FA1201D-4330-4FA8-8AE9-B877473B6441'

EXAMPLE: Install updates by KB number:

Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -Verbose -IgnoreReboot -KBArticleID 'KB2267602', 'KB4533002'

Full Script: Get/Install Available Microsoft Updates

With the exception of the "Install Specific Microsoft KB" script, all scripts are really the same with the only difference being the very last line of code:

Get-WindowsUpdate -MicrosoftUpdate -Verbose

You can change this with any of the lines above to alter what you want to install:

Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -Verbose -IgnoreReboot -Category 'Critical Updates', 'Security Updates', 'Updates'

Here's the full script:

<#
PSWindowsUpdates PowerShell Module Script adapted for PDQ Products
Created: 3/14/2023 C2
Updated: 5/2/2023

General Categories:
Critical Updates', 'Definition Updates', 'Drivers', 'Feature Packs', 'Security Updates', 'Service Packs', 'Tools', 'Update Rollups', 'Updates', 'Upgrades', 'Microsoft'

Category CategoryIDs
Application 5C9376AB-8CE6-464A-B136-22113DD69801
Connectors 434DE588-ED14-48F5-8EED-A15E09A991F6
Critical Updates E6CF1350-C01B-414D-A61F-263D14D133B4
Definition Updates E0789628-CE08-4437-BE74-2495B842F43B
Developer Kits E140075D-8433-45C3-AD87-E72345B36078
Feature Packs B54E7D24-7ADD-428F-8B75-90A396FA584F
Guidance 9511D615-35B2-47BB-927F-F73D8E9260BB
Security Updates 0FA1201D-4330-4FA8-8AE9-B877473B6441
ServicePacks 68C5B0A3-D1A6-4553-AE49-01D3A7827828
Tools B4832BD8-E735-4761-8DAF-37F882276DAB
UpdateRollups 28BC880E-0592-4CBF-8F95-C79B17911D5F
Updates CD5FFD1E-E932-4E3A-BF74-18BF0B1BBD83
Source: https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ff357803(v=vs.85)

EXAMPLE: Get all available patches from Microsoft
Get-WindowsUpdate -MicrosoftUpdate -Verbose

EXAMPLE: Exclude information:
Get-WindowsUpdate -MicrosoftUpdate -Verbose -NotCategory 'Drivers' -NotTitle 'OneDrive' -NotKBArticleID 'KB4489873'

EXAMPLE: Install updates by Category
Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -Verbose -IgnoreReboot -Category 'Critical Updates', 'Security Updates', 'Updates'

EXAMPLE: Install updates by CategoryID
Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -Verbose -IgnoreReboot -CategoryIDs 'E6CF1350-C01B-414D-A61F-263D14D133B4', 'CD5FFD1E-E932-4E3A-BF74-18BF0B1BBD83', '0FA1201D-4330-4FA8-8AE9-B877473B6441'

EXAMPLE: Install updates by KB number:
Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -Verbose -IgnoreReboot -KBArticleID 'KB2267602', 'KB4533002'

#>

$ProviderName = "NuGet"
$Module = "PSWindowsUpdate"
$RegPath = "HKLM:\Software\Policies\Microsoft\Windows\WindowsUpdate"

Write-Output "Checking if $ProviderName Provider is installed..."
IF(Get-PackageProvider -Name $ProviderName){
Write-Output "$ProviderName Provider is installed."
}
ELSE {
Write-Output "$ProviderName Provider is NOT installed."

Write-Output "Attempting to set SecurityProtocol to Tls12 for Net.ServicePointManager..."
TRY {
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
}
CATCH {
Write-Output "Unable to set SecurityProtocol to Tls12 for Net.ServicePointManager: $($_.Exception.Message)"
}

Write-Output "Attempting to install $ProviderName Provider..."
TRY {
Install-PackageProvider -Name $ProviderName -Force -confirm:$False
}
CATCH {
THROW "Unable to install $ProviderName Provider $($_.Exception.Message)"
}
}

Write-Output "Checking if $Module module is installed..."
IF(Get-Module -ListAvailable -Name $Module){
Write-Output "$Module module is installed."
}
ELSE{
Write-Output "$Module module is NOT Installed."
Write-Output "Attempting to install $Module module..."
TRY {
Install-Module -Name $Module -Force -Confirm:$False
}
CATCH {
THROW "Unable to install $Module module $($_.Exception.Message)"
}
}

Write-Output "Checking for Old Windows Update Registry entries..."
IF(Test-Path $RegPath){
DO {
$service = Get-Service -Name wuauserv
IF ($service.Status -eq "Stopped") {
Write-Output "The Windows Update service has been stopped."
break
} ELSE {
Write-Output "Stopping the Windows Update service..."
Stop-Service -Name wuauserv
Start-Sleep -Seconds 5
}
} UNTIL ($service.Status -eq "Stopped")

Write-Output "Removing Old Windows Update registry entries..."
Remove-Item $RegPath -Recurse
Write-Output "Windows Update Registry entries cleaned."

DO {
$service = Get-Service -Name wuauserv
IF ($service.Status -eq "Running") {
Write-Output "The Windows Update service has been started."
break
} ELSE {
Write-Output "Starting the Windows Update service..."
Start-Service -Name wuauserv
Start-Sleep -Seconds 5
}
} UNTIL ($service.Status -eq "Running")
}

Write-Output "Importing $Module Module into PowerShell session..."
TRY {
Import-Module $Module
}
CATCH {
THROW "Unable to load $Module Module into PowerShell session $($_.Exception.Message)"
}

Write-Output "Retrieving Available Microsoft Updates..."
TRY {
Get-WindowsUpdate -MicrosoftUpdate -Verbose
}
CATCH {
THROW "$Module failed to Retrieve Available Microsoft Updates $($_.Exception.Message)"
}

IF ($null -ne $GWU) {
$GWU | ForEach-Object {

[PSCustomObject]@{
"KB" = $_.KB
"Title" = $_.Title
"Size" = $_.Size
"Type" = switch ($_.Type) {
1 { "Software" }
2 { "Driver" }
Default { "Unknown" } 
}
"SupportUrl" = $_.SupportUrl
"Description" = $_.Description
}
}
}
ELSE {
[PSCustomObject]@{
"KB" = "No Applicable Updates"
"Title" = $null
"Size" = $null
"Type" = $null
"SupportUrl" = $null
"Description" = $null
}
}

Full Script: Install Specific Microsoft KB

This script includes an additional parameter block to change and read the KBNumber you wish to deploy:

[CmdletBinding()]param ([Parameter(Mandatory = $true)][String]$KBArticleID)Write-Host "KBArticleID is $KBArticleID"

The PowerShell script then looks for an additional parameter when running the script:

-KBArticleID 'KB8675309'

Here's the full script:

<#
PSWindowsUpdates PowerShell Module Script adapted for PDQ Products
Created: 3/14/2023 C2
Updated: 5/2/2023

General Categories:
Critical Updates', 'Definition Updates', 'Drivers', 'Feature Packs', 'Security Updates', 'Service Packs', 'Tools', 'Update Rollups', 'Updates', 'Upgrades', 'Microsoft'

Category CategoryIDs
Application 5C9376AB-8CE6-464A-B136-22113DD69801
Connectors 434DE588-ED14-48F5-8EED-A15E09A991F6
Critical Updates E6CF1350-C01B-414D-A61F-263D14D133B4
Definition Updates E0789628-CE08-4437-BE74-2495B842F43B
Developer Kits E140075D-8433-45C3-AD87-E72345B36078
Feature Packs B54E7D24-7ADD-428F-8B75-90A396FA584F
Guidance 9511D615-35B2-47BB-927F-F73D8E9260BB
Security Updates 0FA1201D-4330-4FA8-8AE9-B877473B6441
ServicePacks 68C5B0A3-D1A6-4553-AE49-01D3A7827828
Tools B4832BD8-E735-4761-8DAF-37F882276DAB
UpdateRollups 28BC880E-0592-4CBF-8F95-C79B17911D5F
Updates CD5FFD1E-E932-4E3A-BF74-18BF0B1BBD83
Source: https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ff357803(v=vs.85)

EXAMPLE: Get all available patches from Microsoft
Get-WindowsUpdate -MicrosoftUpdate -Verbose

EXAMPLE: Exclude information:
Get-WindowsUpdate -MicrosoftUpdate -Verbose -NotCategory 'Drivers' -NotTitle 'OneDrive' -NotKBArticleID 'KB4489873'

EXAMPLE: Install updates by Category
Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -Verbose -IgnoreReboot -Category 'Critical Updates', 'Security Updates', 'Updates'

EXAMPLE: Install updates by CategoryID
Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -Verbose -IgnoreReboot -CategoryIDs 'E6CF1350-C01B-414D-A61F-263D14D133B4', 'CD5FFD1E-E932-4E3A-BF74-18BF0B1BBD83', '0FA1201D-4330-4FA8-8AE9-B877473B6441'

EXAMPLE: Install updates by KB number:
Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -Verbose -IgnoreReboot -KBArticleID 'KB2267602', 'KB4533002'

#>

[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[String]$KBArticleID
)
Write-Output "$KBArticleID selected to install."

$ProviderName = "NuGet"
$Module = "PSWindowsUpdate"
$RegPath = "HKLM:\Software\Policies\Microsoft\Windows\WindowsUpdate"

Write-Output "Checking if $ProviderName Provider is installed..."
IF(Get-PackageProvider -Name $ProviderName){
Write-Output "$ProviderName Provider is installed."
}
ELSE {
Write-Output "$ProviderName Provider is NOT installed."

Write-Output "Attempting to set SecurityProtocol to Tls12 for Net.ServicePointManager..."
TRY {
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
}
CATCH {
Write-Output "Unable to set SecurityProtocol to Tls12 for Net.ServicePointManager: $($_.Exception.Message)"
}

Write-Output "Attempting to install $ProviderName Provider..."
TRY {
Install-PackageProvider -Name $ProviderName -Force -confirm:$False
}
CATCH {
THROW "Unable to install $ProviderName Provider $($_.Exception.Message)"
}
}

Write-Output "Checking if $Module module is installed..."
IF(Get-Module -ListAvailable -Name $Module){
Write-Output "$Module module is installed."
}
ELSE{
Write-Output "$Module module is NOT Installed."
Write-Output "Attempting to install $Module module..."
TRY {
Install-Module -Name $Module -Force -Confirm:$False
}
CATCH {
THROW "Unable to install $Module module $($_.Exception.Message)"
}
}

Write-Output "Checking for Old Windows Update Registry entries..."
IF(Test-Path $RegPath){
DO {
$service = Get-Service -Name wuauserv
IF ($service.Status -eq "Stopped") {
Write-Output "The Windows Update service has been stopped."
break
} ELSE {
Write-Output "Stopping the Windows Update service..."
Stop-Service -Name wuauserv
Start-Sleep -Seconds 5
}
} UNTIL ($service.Status -eq "Stopped")

Write-Output "Removing Old Windows Update registry entries..."
Remove-Item $RegPath -Recurse
Write-Output "Windows Update Registry entries cleaned."

DO {
$service = Get-Service -Name wuauserv
IF ($service.Status -eq "Running") {
Write-Output "The Windows Update service has been started."
break
} ELSE {
Write-Output "Starting the Windows Update service..."
Start-Service -Name wuauserv
Start-Sleep -Seconds 5
}
} UNTIL ($service.Status -eq "Running")
}

Write-Output "Importing $Module Module into PowerShell session..."
TRY {
Import-Module $Module
}
CATCH {
THROW "Unable to load $Module Module into PowerShell session $($_.Exception.Message)"
}

Write-Output "Installing Selected Microsoft Updates..."
TRY {
Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -Verbose -IgnoreReboot -KBArticleID $KBArticleID
}
CATCH {
THROW "$Module failed to Install Selected Microsoft Updates $($_.Exception.Message)"
}
Still have a question or want to share what you have learned? Visit our Community to get help and collaborate with others.