This has been a few months in the making to get what I think is a decent build of my WSUS Administrator Module. My goal with this module was to make something that provided enough use for most aspects of WSUS administration. With that, I have put together 40 advanced functions that provide access to various parts of WSUS. Some of these are commands to query different parts of wsus, such as clients, updates, server configurations, etc… Other parts allow for making configuration changes or approving/disapproving updates, creating or removing Target groups and adding/removing clients from Target groups. Some of the commands, such as ones that approve/decline updates, adds/removes a group, etc… have the whatif and confirm capabilities so you can verify that everything will happen as intended.
I have spent the last week testing it and working out all of the bugs, but most likely there are still some quirks here and there. I would appreciate any comments, both positive and negative as anything said will help to make the next version of this module better. I already have a list of probably 4 or 5 things that I want to add to this module for the next version.
So without further ado, I will walk through a few of the basic things in my module…
Importing the module
IMPORTANT!! You must have the WSUS Administrator Console installed on whichever computer that you will be running this function from. Download available here.
Be sure to save the module off as a .psm1 file so you can run the Import-Module cmdlet. Once you import the module, it will display a message telling you a couple of things that you can do to get started. I modeled this after the PowerCLI module as it seemed like a pretty good idea to show a couple of key things such as finding all of the commands available and how to make the initial connection to the server.
Available Commands
As I said before, I currently have 40 available advanced functions to perform a variety of tasks in WSUS. Below is a list of the commands:
Add-WSUSClientToGroup
Approve-WSUSUpdate
Connect-WSUSServer
Convert-WSUSTargetGroup
Deny-WSUSUpdate
Disconnect-WSUSServer
Get-WSUSChildServers
Get-WSUSClient
Get-WSUSClientGroupMembership
Get-WSUSClients
Get-WSUSClientsInGroup
Get-WSUSCommands
Get-WSUSContentDownloadProgress
Get-WSUSDatabaseConfig
Get-WSUSDownstreamServers
Get-WSUSEmailConfig
Get-WSUSEvents
Get-WSUSGroup
Get-WSUSGroups
Get-WSUSServer
Get-WSUSStatus
Get-WSUSSubscription
Get-WSUSSyncHistory
Get-WSUSSyncProgress
Get-WSUSUpdate
Get-WSUSUpdateCategories
Get-WSUSUpdates
New-WSUSGroup
Remove-WSUSClient
Remove-WSUSClientFromGroup
Remove-WSUSGroup
Remove-WSUSUpdate
Resume-WSUSDownloads
Resume-WSUSUpdateDownload
Set-WSUSEmailConfig
Start-WSUSCleanup
Start-WSUSSync
Stop-WSUSDownloads
Stop-WSUSSync
Stop-WSUSUpdateDownload
Making Initial Connection to WSUS Server
To make the initial connection to the WSUS server, use the Connect-WSUSServer function. This will allow you to use the other advanced functions that are available within this module.
Now that the connection has been made, we can begin looking at a couple of commands that will probably be getting a fair amount of use.
Viewing Updates
The Get-WSUSUpdates advanced function will grab all of the updates, so be careful using it as it may take a while to grab every update. Using the following command, I can pull the first 5 updates.
Get-WSUSUpdates | Select -first 5 | Select Title, KnowledgeBaseArticles, UpdateClassificationTitle
If you want to look for a specific update, you can use Get-WSUSUpdate to accomplish this. This works much faster and is more helpful for filtering for specific updates.
Get-WSUSUpdate -Update "819639"
WSUS Target Groups
You can view the current WSUS Target groups using the Get-WSUSGroups function.
Creating a new WSUS Target group is as simple as using the New-WSUSGroup command.
New-WSUSGroup -Group "NewWSUSGroup"
And removing a group using Remove-WSUSGroup.
Remove-WSUSGroup -Name "NewWSUSGroup"
Approving and Declining WSUS Updates
There are a couple of ways to both approve and decline updates within this module. The first way is supplying a string value and have the command search for and approve/decline the updates.
For approving and update, you have a few other things that are required in order make the approval successful. The first is to supply a group that the update will be approved for. Second, you must provide an Action type for the update approval, typically “Install”. The third and not a required option is to provide a deadline for the update.
Approve-WSUSUpdate -Group "Domain Servers" -Update "819639" -Action Install
Declining is much easier and only requires the update string to be entered.
Deny-WSUSUpdate -Update "819639"
Besides using the string method, both the Approve-WSUSUpdate and Deny-WSUSUpdate accepts input via the pipeline and allows you to use objects as well. So combining the Get-WSUSUpdate or Get-WSUSUpdates with the approving or declining of updates will work just as well.
Get-WSUSUpdate -Update "819639" | Approve-WSUSUpdate -Group "Domain Servers" -Action Install
Get-WSUSUpdate -Update "819639" | Deny-WSUSUpdate
WSUS Synchronization
I have a few advanced functions that work with synchronization, such as pulling synchronization events with Get-WSUSSyncHistory, starting a manual synchronization with Start-WSUSSync and finding the current status of a synchronization using Get-WSUSSyncProgress.
Get-WSUSSyncHistory | select -first 1
Start-WSUSSync
Get-WSUSSyncProgress
There is a parameter switch with Get-WSUSSyncProgress and Start-WSUSSync called ‘monitor’ which starts a background job that will alert you with a popup message stating that the synchronization has been completed.
This module is available for download from both the Script Repository and at Poshcode along with the code being available below.
Currently, the code I submitted to PoshCode appears to be getting truncated. I left some feedback asking about this and am waiting on a reply. I will try again to re-post the code and see if it works, and if so, I will remove this message.
21NOV2010: Updated code for Connect-WSUSServer to allow for adding what port you want to connect to on the WSUS Server in case the server was configured for a port other than the default ports.
Write-Host "`n"
Write-Host "`t`tWSUS Administrator Module 1.0"
Write-Host "`n"
Write-Host -nonewline "Make initial connection to WSUS Server:`t"
Write-Host -fore Yellow "Connect-WSUSServer"
Write-Host -nonewline "Disconnect from WSUS Server:`t`t"
Write-Host -fore Yellow "Disconnect-WSUSServer"
Write-Host -nonewline "List all available commands:`t`t"
Write-Host -fore Yellow "Get-WSUSCommands"
Write-Host "`n"
function Get-WSUSCommands {
<#
.SYNOPSIS
Lists all WSUS functions available from this module.
.DESCRIPTION
Lists all WSUS functions available from this module.
.NOTES
Name: Get-WSUSCommand
Author: Boe Prox
DateCreated: 18Oct2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Get-WSUSCommands
Description
-----------
This command lists all of the available WSUS commands in the module.
#>
[cmdletbinding()]
Param ()
#List all WSUS functions available
Get-Command *WSUS* -CommandType Function | Sort-Object Name
}
function Connect-WSUSServer {
<#
.SYNOPSIS
Retrieves the last check-in times of clients on WSUS.
.DESCRIPTION
Retrieves the last check-in times of clients on WSUS. You will need to run this on a machine that
has the WSUS Administrator console installed.
.PARAMETER WsusServer
Name of WSUS server to query against.
.PARAMETER Secure
Determines if a secure connection will be used to connect to the WSUS server. If not used, then a non-secure
connection will be used.
.PARAMETER Port
Port number if default ports 80 and 443 not used
.NOTES
Name: Get-LastCheckIn
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Connect-WSUSServer -wsusserver "server1"
Description
-----------
This command will make the connection to the WSUS using an unsecure port (Default:80).
.EXAMPLE
Connect-WSUSServer -wsusserver "server1" -secure
Description
-----------
This command will make a secure connection (Default: 443) to a WSUS server.
.EXAMPLE
Connect-WSUSServer -wsusserver "server1" -port 8560
Description
-----------
This command will make the connection to the WSUS using a defined port 8560.
#>
[cmdletbinding(
DefaultParameterSetName = 'wsus',
ConfirmImpact = 'low'
)]
Param(
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = '',
ValueFromPipeline = $True)]
[string]$WsusServer,
[Parameter(
Mandatory = $False,
Position = 1,
ParameterSetName = '',
ValueFromPipeline = $False)]
[switch]$Secure,
[Parameter(
Mandatory = $False,
Position = 2,
ParameterSetName = 'port',
ValueFromPipeline = $False)]
[int]$port
)
#Load required assemblies
[void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")
#Make connection to WSUS server
Write-Host -ForegroundColor Yellow "Attempting connection to WSUS Server: $($wsusserver)"
$ErrorActionPreference = 'stop'
Try {
If ($secure) {
Switch ($pscmdlet.ParameterSetName) {
"wsus" {
$Global:wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($wsusserver,$True)
$Wsus | Select Name, Version,PortNumber
}
"port" {
$Global:wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($wsusserver,$True,$port)
$Wsus | Select Name, Version,PortNumber
}
}
}
Else {
Switch ($pscmdlet.ParameterSetName) {
"wsus" {
$Global:wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($wsusserver,$False)
$Wsus | Select Name, Version,PortNumber
}
"port" {
$Global:wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($wsusserver,$False,$port)
$Wsus | Select Name, Version,PortNumber
}
}
}
}
Catch {
Write-Error "Unable to connect to $($wsusserver)!`n$($error[0])"
}
}
function Disconnect-WSUSServer {
<#
.SYNOPSIS
Disconnects session against WSUS server.
.DESCRIPTION
Disconnects session against WSUS server.
.NOTES
Name: Disconnect-WSUSServer
Author: Boe Prox
DateCreated: 27Oct2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Disconnect-WSUSServer
Description
-----------
This command will disconnect the session to the WSUS server.
#>
[cmdletbinding()]
Param ()
#Disconnect WSUS session by removing the variable
Remove-Variable -Name wsus -Force
}
function Get-WSUSClients {
<#
.SYNOPSIS
Retrieves a list of all of the clients in WSUS.
.DESCRIPTION
Retrieves a list of all of the clients in WSUS.
.NOTES
Name: Get-WSUSClients
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Get-WSUSClients
Description
-----------
This command will list every client in WSUS.
#>
[cmdletbinding()]
Param ()
#Gather all computers in WSUS
$wsus.GetComputerTargets()
}
function Start-WSUSSync {
<#
.SYNOPSIS
Start synchronization on WSUS server.
.DESCRIPTION
Start synchronization on WSUS server.
.PARAMETER Monitor
Starts a synchronization and runs a background job to monitor currently running content download and
notifies user when completed.
.NOTES
Name: Start-WSUSSync
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Start-WSUSSync
Description
-----------
This command will begin a manual sychronization on WSUS with the defined update source.
.EXAMPLE
Start-WSUSSync -monitor
Description
-----------
This command will begin a manual synchronization on WSUS and will begin a background job that will notifiy via
pop-up message when the synchronization has completed.
#>
[cmdletbinding(
DefaultParameterSetName = 'monitor',
ConfirmImpact = 'low',
SupportsShouldProcess = $True
)]
Param (
[Parameter(
Mandatory = $False,
Position = 0,
ParameterSetName = 'monitor',
ValueFromPipeline = $False)]
[switch]$Monitor
)
$sub = $wsus.GetSubscription()
$sync = $sub.GetSynchronizationProgress()
If ($monitor) {
#Stop and remove any jobs for SyncMonitoring
$jobs = Get-Job | ? {$_.Name -eq "WSUSSyncProgressMonitor"}
If ($jobs) {
$jobs | Stop-Job
$jobs | Remove-Job
}
#Start WSUS synchronization
If ($pscmdlet.ShouldProcess($($wsus.name))) {
$sub.StartSynchronization()
"Synchronization have been started."
Start-Sleep -Seconds 3
Start-Job -Name "WSUSSyncProgressMonitor" -ArgumentList $sync -ScriptBlock {
Param (
$sync
)
#Load required assemblies for message window
[void] [System.Reflection.Assembly]::LoadWithPartialName(“System.Windows.Forms”)
While ($sync.Phase -ne "NotProcessing") {
$null
}
[System.Windows.Forms.MessageBox]::Show("Synchronization has been completed on WSUS",”Information”)
} | Out-Null
}
}
Else {
#Start WSUS synchronization
If ($pscmdlet.ShouldProcess($($wsus.name))) {
$sub.StartSynchronization()
"Synchronization have been started."
}
}
}
function Stop-WSUSSync {
<#
.SYNOPSIS
Stops a currently running WSUS sync.
.DESCRIPTION
Stops a currently running WSUS sync.
.NOTES
Name: Stop-WSUSSync
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Stop-WSUSSync
Description
-----------
This command will stop a currently running WSUS synchronization.
#>
[cmdletbinding(
DefaultParameterSetName = 'update',
ConfirmImpact = 'low',
SupportsShouldProcess = $True
)]
Param()
$sub = $wsus.GetSubscription()
#Cancel synchronization running on WSUS
If ($pscmdlet.ShouldProcess($($wsus.name))) {
$sub.StopSynchronization()
"Synchronization have been cancelled."
}
}
function Get-WSUSSyncHistory {
<#
.SYNOPSIS
Retrieves the synchronization history of the WSUS server.
.DESCRIPTION
Retrieves the synchronization history of the WSUS server.
.NOTES
Name: Get-WSUSSyncHistory
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Get-WSUSSyncHistory
Description
-----------
This command will list out the entire synchronization history of the WSUS server.
#>
[cmdletbinding()]
Param ()
$sub = $wsus.GetSubscription()
$sub.GetSynchronizationHistory()
}
function Get-WSUSSyncProgress {
<#
.SYNOPSIS
Displays the current progress of a WSUS synchronization.
.DESCRIPTION
Displays the current progress of a WSUS synchronization.
.PARAMETER Monitor
Runs a background job to monitor currently running synchonization and notifies user when completed.
.NOTES
Name: Get-WSUSSyncProgress
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Get-WSUSSyncProgress
Description
-----------
This command will show you the current status of the WSUS sync.
.EXAMPLE
Get-WSUSSyncProgress -monitor
Description
-----------
This command will begin a background job that will notify you when the WSUS synchronization
has been completed.
#>
[cmdletbinding()]
Param (
[Parameter(
Mandatory = $False,
Position = 0,
ParameterSetName = 'monitor',
ValueFromPipeline = $False)]
[switch]$Monitor
)
$sub = $wsus.GetSubscription()
If ($monitor) {
$job = Get-Job
If ($job) {
$job = Get-Job -Name "WSUSSyncProgressMonitor"
}
If ($job) {
Get-Job -Name "WSUSSyncProgressMonitor" | Stop-Job
Get-Job -Name "WSUSSyncProgressMonitor" | Remove-Job
}
Start-Job -Name "WSUSSyncProgressMonitor" -ArgumentList $sub -ScriptBlock {
Param (
$sub
)
#Load required assemblies for message window
[void] [System.Reflection.Assembly]::LoadWithPartialName(“System.Windows.Forms”)
While (($sub.GetSynchronizationProgress()).Phase -ne "NotProcessing") {
$null
}
[System.Windows.Forms.MessageBox]::Show("Synchronization has been completed on WSUS",”Information”)
} | Out-Null
}
Else {
#Gather all child servers in WSUS
$sub.GetSynchronizationProgress()
}
}
function Get-WSUSEvents {
<#
.SYNOPSIS
Retrieves all WSUS events.
.DESCRIPTION
Retrieves all WSUS events from the WSUS server.
.NOTES
Name: Get-WSUSEvents
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Get-WSUSEvents
Description
-----------
This command will show you all of the WSUS events.
#>
[cmdletbinding()]
Param ()
$sub = $wsus.GetSubscription()
$sub.GetEventHistory()
}
function Get-WSUSGroups {
<#
.SYNOPSIS
Retrieves all of the WSUS Target Groups.
.DESCRIPTION
Retrieves all of the WSUS Target Groups.
.NOTES
Name: Get-WSUSGroups
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Get-WSUSGroups
Description
-----------
This command will list out all of the WSUS Target groups and their respective IDs.
#>
[cmdletbinding()]
Param ()
$wsus.GetComputerTargetGroups()
}
function Get-WSUSServer {
<#
.SYNOPSIS
Retrieves connection and configuration information from the WSUS server.
.DESCRIPTION
Retrieves connection and configuration information from the WSUS server.
.PARAMETER Configuration
Lists more configuration information from WSUS Server
.NOTES
Name: Get-WSUSServer
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Get-WSUSServer
Description
-----------
This command will display basic information regarding the WSUS server.
.EXAMPLE
Get-WSUSServer -configuration
Description
-----------
This command will list out more detailed information regarding the configuration of the WSUS server.
#>
[cmdletbinding(
DefaultParameterSetName = 'wsus',
ConfirmImpact = 'low'
)]
Param(
[Parameter(
Mandatory = $False,
Position = 0,
ParameterSetName = 'wsus',
ValueFromPipeline = $False)]
[switch]$Configuration
)
If ($configuration) {
$wsus.GetConfiguration()
}
Else {
$wsus
}
}
function Get-WSUSUpdates {
<#
.SYNOPSIS
Retrieves all of the updates from a WSUS server.
.DESCRIPTION
Retrieves all of the updates from a WSUS server.
.NOTES
Name: Get-WSUSUpdates
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Get-WSUSUpdates
Description
-----------
This command will list out every update that is in WSUS's database whether it has been approved or not.
#>
[cmdletbinding()]
Param ()
$wsus.GetUpdates()
}
function Get-WSUSEmailConfig {
<#
.SYNOPSIS
Retrieves the email notification configuration from WSUS.
.DESCRIPTION
Retrieves the email notification configuration from WSUS.
.PARAMETER SendTestEmail
Optional switch that will send a test email to the configured email addresses
.NOTES
Name: Get-WSUSEmailConfig
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Get-WSUSEmailConfig
Description
-----------
This command will display the configuration of the email notifications.
.EXAMPLE
Get-WSUSEmailConfig -SendTestEmail
Description
-----------
This command will send a test email to the address or addresses in the To field.
#>
[cmdletbinding(
DefaultParameterSetName = 'wsus',
ConfirmImpact = 'low'
)]
Param(
[Parameter(
Mandatory = $False,
Position = 0,
ParameterSetName = 'wsus',
ValueFromPipeline = $False)]
[switch]$SendTestEmail
)
$email = $wsus.GetEmailNotificationConfiguration()
If ($SendTestEmail) {
$email.SendTestEmail()
Write-Host -fore Green "Test email sent."
}
Else {
$email
}
}
function Get-WSUSUpdateCategories {
<#
.SYNOPSIS
Retrieves the list of Update categories available from WSUS.
.DESCRIPTION
Retrieves the list of Update categories available from WSUS.
.NOTES
Name: Get-WSUSUpdateCategories
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Get-WSUSUpdateCategories
Description
-----------
This command will list all of the categories for updates in WSUS.
#>
[cmdletbinding()]
Param ()
$wsus.GetUpdateCategories()
}
function Get-WSUSStatus {
<#
.SYNOPSIS
Retrieves a list of all updates and their statuses along with computer statuses.
.DESCRIPTION
Retrieves a list of all updates and their statuses along with computer statuses.
.NOTES
Name: Get-WSUSStatus
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Get-WSUSStatus
Description
-----------
This command will display the status of the WSUS server along with update statuses.
#>
[cmdletbinding()]
Param ()
$wsus.getstatus()
}
function Set-WSUSEmailConfig {
<#
.SYNOPSIS
Configures the email notifications on a WSUS server.
.DESCRIPTION
Configures the email notifications on a WSUS server. It is important to note that the email address to send
the emails to is Read-Only and can only be configured from the WSUS Admin Console. After the settings have been
changed, the new configuration will be displayed.
.PARAMETER EmailLanguage
What type of language to send the email in.
.PARAMETER SenderDisplayName
The friendly name of where the email is coming from.
.PARAMETER SenderEmailAddress
The senders email address
.PARAMETER SendStatusNotification
Determines if an email will be sent for a status notification
.PARAMETER SendSyncnotification
Determines if an email will be sent after a sync by WSUS
.PARAMETER SMTPHostname
Server name of the smtp server to send email from
.PARAMETER SMTPPort
Port number to be used to connect to smtp server to send email
.PARAMETER SmtpServerRequiresAuthentication
Used if smtp server requires authentication
.PARAMETER SmtpUserName
Username to submit if required by smtp server
.PARAMETER StatusNotificationFrequency
Frequency (Daily or Weekly) to send notifications
.PARAMETER StatusNotificationTimeOfDay
Date/Time to send notifications
.PARAMETER UpdateServer
Name of the WSUS update server
.PARAMETER SmtpPassword
Password to user for smtp server connection.
.NOTES
Name: Set-WSUSEmailConfig
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Set-WSUSEmailConfig -SenderDisplayName "WSUSAdmin" -SenderEmailAddress "wsusadmin@domain.com"
Description
-----------
This command will change the sender name and email address for email notifications and then display the new settings.
#>
[cmdletbinding(
DefaultParameterSetName = 'wsus',
ConfirmImpact = 'low'
)]
Param(
[Parameter(
Mandatory = $False, Position = 0,
ParameterSetName = '', ValueFromPipeline = $False)]
[string]$EmailLanguage,
[Parameter(
Mandatory = $False, Position = 1,
ParameterSetName = '', ValueFromPipeline = $False)]
[string]$SenderDisplayName,
[Parameter(
Mandatory = $False, Position = 2,
ParameterSetName = '', ValueFromPipeline = $False)]
[string]$SenderEmailAddress,
[Parameter(
Mandatory = $False, Position = 3,
ParameterSetName = '', ValueFromPipeline = $False)]
[string][ValidateSet("True","False")]$SendStatusNotification,
[Parameter(
Mandatory = $False, Position = 4,
ParameterSetName = '',ValueFromPipeline = $False)]
[string][ValidateSet("True","False")]$SendSyncnotification,
[Parameter(
Mandatory = $False, Position = 5,
ParameterSetName = '', ValueFromPipeline = $False)]
[string]$SMTPHostname,
[Parameter(
Mandatory = $False, Position = 6,
ParameterSetName = '', ValueFromPipeline = $False)]
[int]$SMTPPort,
[Parameter(
Mandatory = $False, Position = 7,
ParameterSetName = '', ValueFromPipeline = $False)]
[string][ValidateSet("True","False")]$SmtpServerRequiresAuthentication,
[Parameter(
Mandatory = $False, Position = 8,
ParameterSetName = 'account', ValueFromPipeline = $False)]
[string]$SmtpUserName,
[Parameter(
Mandatory = $False, Position = 9,
ParameterSetName = '', ValueFromPipeline = $False)]
[string][ValidateSet("Daily","Weekly")]$StatusNotificationFrequency,
[Parameter(
Mandatory = $False, Position = 10,
ParameterSetName = '', ValueFromPipeline = $False)]
[string]$StatusNotificationTimeOfDay,
[Parameter(
Mandatory = $False,Position = 11,
ParameterSetName = '',ValueFromPipeline = $False)]
[string]$UpdateServer,
[Parameter(
Mandatory = $False,Position = 12,
ParameterSetName = 'account',ValueFromPipeline = $False)]
[string]$SmtpPassword
)
#Configure Email Notifications
$email = $wsus.GetEmailNotificationConfiguration()
$ErrorActionPreference = 'stop'
Try {
If ($StatusNotificationTimeOfDay) {
#Validate Notification Time of Day Parameter
If (!([regex]::ismatch($StatusNotificationTimeOfDay,"^\d{2}:\d{2}$"))) {
Write-Error "$($StatusNotificationTimeOfDay) is not a valid time to use!`nMust be 'NN:NN'"
}
Else {
$email.StatusNotificationTimeOfDay = $StatusNotificationTimeOfDay
}
}
If ($UpdateServer) {$email.UpdateServer = $UpdateServer}
If ($EmailLanguage) {$email.EmailLanguage = $EmailLanguage}
If ($SenderDisplayName) {$email.SenderDisplayName = $SenderDisplayName}
If ($SenderEmailAddress) {
#Validate Email Address Parameter
If (!([regex]::ismatch($SenderEmailAddress,"^\w+@\w+\.com|mil|org|net$"))) {
Write-Error "$($SenderEmailAddress) is not a valid email address!`nMust be 'xxxx@xxxxx.xxx'"
}
Else {
$email.SenderEmailAddress = $SenderEmailAddress
}
}
If ($SMTPHostname) {$email.SMTPHostname = $SMTPHostname}
If ($SMTPPort) {$email.SMTPPort = $SMTPPort}
If ($SmtpServerRequiresAuthentication) {$email.SmtpServerRequiresAuthentication = $SmtpServerRequiresAuthentication}
If ($SmtpUserName) {$email.SmtpUserName = $SmtpUserName}
If ($SmtpPassword) {$mail.SetSmtpUserPassword($SmtpPassword)}
Switch ($StatusNotificationFrequency) {
"Daily" {$email.StatusNotificationFrequency = [Microsoft.UpdateServices.Administration.EmailStatusNotificationFrequency]::Daily}
"Weekly" {$email.StatusNotificationFrequency = [Microsoft.UpdateServices.Administration.EmailStatusNotificationFrequency]::Weekly}
Default {$Null}
}
Switch ($SendStatusNotification) {
"True" {$email.SendStatusNotification = 1}
"False" {$email.SendStatusNotification = 0}
Default {$Null}
}
Switch ($SendSyncNotification) {
"True" {$email.SendSyncNotification = 1}
"False" {$email.SendSyncNotification = 0}
Default {$Null}
}
}
Catch {
Write-Error "$($error[0])"
}
#Save Configuration Changes
Try {
$email.Save()
Write-Host -fore Green "Email settings changed"
$email
}
Catch {
Write-Error "$($error[0])"
}
}
function Convert-WSUSTargetGroup {
<#
.SYNOPSIS
Converts the WSUS group from ID to Name or Name to ID.
.DESCRIPTION
Converts the WSUS group from ID to Name or Name to ID.
.PARAMETER Id
GUID of the group to be converted to friendly name
.PARAMETER Name
Name of the group to be converted to a guid
.NOTES
Name: Convert-WSUSTargetGroup
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Convert-WSUSTargetGroup -name "Domain Servers"
Description
-----------
This command will convert the group name "Domain Servers" into the GUID format.
.EXAMPLE
Convert-WSUSTargetGroup -ID "b73ca6ed-5727-47f3-84de-015e03f6a88a"
Description
-----------
This command will convert the given GUID into a friendly name.
#>
[cmdletbinding(
DefaultParameterSetName = 'name',
ConfirmImpact = 'low'
)]
Param(
[Parameter(
Mandatory = $False,
Position = 2,
ParameterSetName = 'id',
ValueFromPipeline = $False)]
[string]$Id,
[Parameter(
Mandatory = $False,
Position = 3,
ParameterSetName = 'name',
ValueFromPipeline = $False)]
[string]$Name
)
If ($name) {
Try {
$group = $wsus.GetComputerTargetGroups() | ? {$_.Name -eq $name}
$group | Select -ExpandProperty ID
}
Catch {
Write-Error "Unable to locate $($name)."
}
}
If ($id) {
Try {
$group = $wsus.GetComputerTargetGroups() | ? {$_.ID -eq $id}
$group | Select -ExpandProperty Name
}
Catch {
Write-Error "Unable to locate $($id)."
}
}
}
function Get-WSUSClientsInGroup {
<#
.SYNOPSIS
Retrieves a list of clients that are members of a group.
.DESCRIPTION
Retrieves a list of clients that are members of a group.
.PARAMETER Id
Retrieves list of clients in group by group guid.
.PARAMETER Name
Retrieves list of clients in group by group name.
.NOTES
Name: Get-WSUSClientsInGroup
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Get-WSUSClientsInGroup -name "Domain Servers"
Description
-----------
This command will list all clients that are members of the specified group via group name.
.EXAMPLE
Get-WSUSClientsInGroup -ID "b73ca6ed-5727-47f3-84de-015e03f6a88a"
Description
-----------
This command will list all clients that are members of the specified group via the group guid.
#>
[cmdletbinding(
DefaultParameterSetName = 'name',
ConfirmImpact = 'low'
)]
Param(
[Parameter(
Mandatory = $False,
Position = 2,
ParameterSetName = 'name',
ValueFromPipeline = $False)]
[string]$Name,
[Parameter(
Mandatory = $False,
Position = 3,
ParameterSetName = 'id',
ValueFromPipeline = $False)]
[string]$Id
)
If ($id) {
($wsus.GetComputerTargetGroups() | ? {$_.Id -eq $id}).GetComputerTargets()
}
If ($name) {
($wsus.GetComputerTargetGroups() | ? {$_.name -eq $name}).GetComputerTargets()
}
}
function Get-WSUSClient {
<#
.SYNOPSIS
Retrieves information about a WSUS client.
.DESCRIPTION
Retrieves information about a WSUS client.
.PARAMETER Computer
Name of the client to search for. Accepts a partial name.
.NOTES
Name: Get-WSUSClient
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Get-WSUSClient -computer "server1"
Description
-----------
This command will search for and display all computers matching the given input.
#>
[cmdletbinding(
DefaultParameterSetName = 'wsus',
ConfirmImpact = 'low'
)]
Param(
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = 'wsus',
ValueFromPipeline = $True)]
[string]$Computer
)
$ErrorActionPreference = 'stop'
#Retrieve computer in WSUS
Try {
$wsus.SearchComputerTargets($computer)
}
Catch {
Write-Error "Unable to retrieve $($computer) from database."
}
}
function New-WSUSGroup {
<#
.SYNOPSIS
Creates a new WSUS Target group.
.DESCRIPTION
Creates a new WSUS Target group.
.PARAMETER Group
Name of group being created.
.PARAMETER ParentGroupName
Name of group being created.
.PARAMETER ParentGroupId
Name of group being created.
.NOTES
Name: New-WSUSGroup
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
New-WSUSGroup -name "TestGroup"
Description
-----------
This command will create a new Target group called 'TestGroup'
.EXAMPLE
New-WSUSGroup -name "TestGroup" -parentgroupname "Domain Servers"
Description
-----------
This command will create a new Target group called 'TestGroup' under the parent group 'Domain Servers'
#>
[cmdletbinding(
DefaultParameterSetName = 'group',
ConfirmImpact = 'low',
SupportsShouldProcess = $True
)]
Param(
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = '',
ValueFromPipeline = $True)]
[string]$Group,
[Parameter(
Mandatory = $False,
Position = 1,
ParameterSetName = 'parentgroup',
ValueFromPipeline = $True)]
[string]$ParentGroupName,
[Parameter(
Mandatory = $False,
Position = 2,
ParameterSetName = 'parentgroup',
ValueFromPipeline = $True)]
[string]$ParentGroupId
)
Process {
#Determine action based on Parameter Set Name
Switch ($pscmdlet.ParameterSetName) {
"group" {
Write-Verbose "Creating computer group"
If ($pscmdlet.ShouldProcess($group)) {
#Create the computer target group
$wsus.CreateComputerTargetGroup($group)
"$($group) has been created."
}
}
"parentgroup" {
If ($parentgroupname) {
#Retrieve group based off of name
Write-Verbose "Querying for parent group"
$parentgroup = Get-WSUSGroups | ? {$_.name -eq $parentgroupname}
If (!$parentgroup) {
Write-Error "Parent Group name `'$parentgroupname`' does not exist in WSUS!"
Break
}
}
If ($parentgroupid) {
#Retrieve group based off of guid
Write-Verbose "Querying for parent group"
$parentgroup = Get-WSUSGroups | ? {$_.id -eq $parentgroupid}
If (!$parentgroup) {
Write-Error "Parent Group id `'$parentgroupid`' does not exist in WSUS!"
Break
}
}
Write-Verbose "Creating computer group"
If ($pscmdlet.ShouldProcess($group)) {
#Create the computer target group
$wsus.CreateComputerTargetGroup($group,$parentgroup)
"$($group) has been created under $($parentgroup.Name)."
}
}
}
}
}
function Get-WSUSUpdate {
<#
.SYNOPSIS
Retrieves information from a wsus update.
.DESCRIPTION
Retrieves information from a wsus update. Depending on how the information is presented in the search, more
than one update may be returned.
.PARAMETER Update
String to search for. This can be any string for the update to include
KB article numbers, name of update, category, etc... Use of wildcards (*,%) not allowed in search!
.NOTES
Name: Get-WSUSUpdate
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Get-WSUSUpdate -update "Exchange"
Description
-----------
This command will list every update that has 'Exchange' in it.
.EXAMPLE
Get-WSUSUpdate -update "925474"
Description
-----------
This command will list every update that has '925474' in it.
#>
[cmdletbinding(
DefaultParameterSetName = 'wsus',
ConfirmImpact = 'low'
)]
Param(
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = 'wsus',
ValueFromPipeline = $True)]
[string]$Update
)
$ErrorActionPreference = 'stop'
#Retrieve computer in WSUS
Try {
$wsus.SearchUpdates($update)
}
Catch {
Write-Error "Unable to retrieve $($update) from database."
}
}
function Remove-WSUSGroup {
<#
.SYNOPSIS
Creates a new WSUS Target group.
.DESCRIPTION
Creates a new WSUS Target group.
.PARAMETER Name
Name of group being deleted.
.PARAMETER Id
Id of group being deleted.
.NOTES
Name: Remove-WSUSGroup
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Remove-WSUSGroup -name "Domain Servers"
Description
-----------
This command will remove the Domain Servers WSUS Target group.
.EXAMPLE
Remove-WSUSGroup -id "fc93e74e-ba59-4593-9ff7-690af1be695f"
Description
-----------
This command will remove the Target group with ID 'fc93e74e-ba59-4593-9ff7-690af1be695f' from WSUS.
#>
[cmdletbinding(
DefaultParameterSetName = 'name',
ConfirmImpact = 'low',
SupportsShouldProcess = $True
)]
Param(
[Parameter(
Mandatory = $False,
Position = 0,
ParameterSetName = 'name',
ValueFromPipeline = $True)]
[string]$Name,
[Parameter(
Mandatory = $False,
Position = 1,
ParameterSetName = 'id',
ValueFromPipeline = $True)]
[string]$Id
)
Process {
#Determine action based on Parameter Set Name
Switch ($pscmdlet.ParameterSetName) {
"name" {
Write-Verbose "Querying for computer group"
$group = Get-WSUSGroup -name $name
If (!$group) {
Write-Error "Group $name does not exist in WSUS!"
Break
}
Else {
If ($pscmdlet.ShouldProcess($name)) {
#Create the computer target group
$group.Delete()
"$($name) has been deleted from WSUS."
}
}
}
"id" {
Write-Verbose "Querying for computer group"
$group = Get-WSUSGroup -id $id
If (!$group) {
Write-Error "Group $id does not exist in WSUS!"
Break
}
If ($pscmdlet.ShouldProcess($id)) {
#Create the computer target group
$group.Delete()
"$($id) has been deleted from WSUS."
}
}
}
}
}
function Add-WSUSClientToGroup {
<#
.SYNOPSIS
Adds a computer client to an existing WSUS group.
.DESCRIPTION
Adds a computer client to an existing WSUS group.
.PARAMETER Group
Name of group to add client to.
.PARAMETER Computer
Name of computer being added to group.
.NOTES
Name: Add-WSUSClientToGroup
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Add-WSUSClientToGroup -group "Domain Servers" -computer "server1"
Description
-----------
This command will add the client "server1" to the WSUS target group "Domain Servers".
#>
[cmdletbinding(
DefaultParameterSetName = 'group',
ConfirmImpact = 'low',
SupportsShouldProcess = $True
)]
Param(
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = 'group',
ValueFromPipeline = $True)]
[string]$Group,
[Parameter(
Mandatory = $False,
Position = 1,
ParameterSetName = 'group',
ValueFromPipeline = $True)]
[string]$Computer
)
#Verify Computer is in WSUS
Write-Verbose "Validating client in WSUS"
$client = Get-WSUSClient -computer $computer
If ($client) {
#Get group object
Write-Verbose "Retrieving group"
$targetgroup = Get-WSUSGroup -name $group
If (!$targetgroup) {
Write-Error "Group $group does not exist in WSUS!"
Break
}
#Add client to group
Write-Verbose "Adding client to group"
If ($pscmdlet.ShouldProcess($($client.fulldomainname))) {
$targetgroup.AddComputerTarget($client)
"$($client.FullDomainName) has been added to $($group)"
}
}
Else {
Write-Error "Computer: $computer is not in WSUS!"
}
}
function Remove-WSUSClientFromGroup {
<#
.SYNOPSIS
Removes a computer client to an existing WSUS group.
.DESCRIPTION
Removes a computer client to an existing WSUS group.
.PARAMETER Group
Name of group to remove client from.
.PARAMETER Computer
Name of computer being removed from group.
.NOTES
Name: Remove-WSUSClientToGroup
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Remove-WSUSClientFromGroup -group "Domain Servers" -computer "server1"
Description
-----------
This command will remove the client "server1" from the WSUS target group "Domain Servers".
#>
[cmdletbinding(
DefaultParameterSetName = 'group',
ConfirmImpact = 'low',
SupportsShouldProcess = $True
)]
Param(
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = 'group',
ValueFromPipeline = $True)]
[string]$Group,
[Parameter(
Mandatory = $False,
Position = 1,
ParameterSetName = 'group',
ValueFromPipeline = $True)]
[string]$Computer
)
#Verify Computer is in WSUS
$client = Get-WSUSClient -computer $computer
If ($client) {
#Get group object
Write-Verbose "Retrieving group"
$targetgroup = Get-WSUSGroup -name $group
If (!$targetgroup) {
Write-Error "Group $group does not exist in WSUS!"
Break
}
#Remove client from group
Write-Verbose "Removing client to group"
If ($pscmdlet.ShouldProcess($($client.fulldomainname))) {
$targetgroup.RemoveComputerTarget($client)
"$($client.fulldomainname) has been removed from $($group)"
}
}
Else {
Write-Error "Computer: $computer is not in WSUS!"
}
}
function Get-WSUSDatabaseConfig {
<#
.SYNOPSIS
Displays the current WSUS database configuration.
.DESCRIPTION
Displays the current WSUS database configuration.
.NOTES
Name: Get-WSUSDatabaseConfig
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Get-WSUSDatabaseConfig
Description
-----------
This command will display the configuration information for the WSUS connection to a database.
#>
[cmdletbinding()]
Param ()
$wsus.GetDatabaseConfiguration()
}
function Get-WSUSSubscription {
<#
.SYNOPSIS
Displays WSUS subscription information.
.DESCRIPTION
Displays WSUS subscription information. You can view the next synchronization time, who last modified the schedule, etc...
.NOTES
Name: Get-WSUSSubscription
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Get-WSUSSubscription
Description
-----------
This command will list out the various subscription information on the WSUS server.
#>
[cmdletbinding()]
Param ()
$wsus.GetSubscription()
}
function Deny-WSUSUpdate {
<#
.SYNOPSIS
Declines an update on WSUS.
.DESCRIPTION
Declines an update on WSUS. Use of the -whatif is advised to be sure you are declining the right patch or patches.
.PARAMETER InputObject
Collection of update/s being declined. This must be an object, otherwise it will fail.
.PARAMETER Update
Name of update/s being declined.
.NOTES
Name: Deny-WSUSUpdate
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Get-WSUSUpdate -update "Exchange 2010" | Deny-WSUSUpdate
Description
-----------
This command will decline all updates with 'Exchange 2010' in its metadata.
.EXAMPLE
Deny-WSUSUpdate -Update "Exchange 2010"
Description
-----------
This command will decline all updates with 'Exchange 2010' in its metadata.
.EXAMPLE
$updates = Get-WSUSUpdate -update "Exchange 2010"
Deny-WSUSUpdate -InputObject $updates
Description
-----------
This command will decline all updates with 'Exchange 2010' in its metadata.
.EXAMPLE
Get-WSUSUpdate -update "Exchange 2010" | Deny-WSUSUpdate
Description
-----------
This command will decline all updates with 'Exchange 2010' in its metadata via the pipeline.
#>
[cmdletbinding(
DefaultParameterSetName = 'collection',
ConfirmImpact = 'low',
SupportsShouldProcess = $True
)]
Param(
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = 'collection',
ValueFromPipeline = $True)]
[system.object]$InputObject,
[Parameter(
Mandatory = $False,
Position = 1,
ParameterSetName = 'string',
ValueFromPipeline = $False)]
[string]$Update
)
Process {
Switch ($pscmdlet.ParameterSetName) {
"Collection" {
Write-Verbose "Using 'Collection' set name"
#Change the collection to patches for use in loop
$patches = $inputobject
}
"String" {
Write-Verbose "Using 'String' set name"
#Gather all updates from given information
Write-Verbose "Searching for updates"
$patches = Get-WSUSUpdate -update $update
}
}
ForEach ($patch in $patches) {
#Decline the update
Write-Verbose "Declining update"
If ($pscmdlet.ShouldProcess($($patch.title))) {
$patch.Decline($True) | out-null
#Print out report of what was declined
New-Object PSObject -Property @{
Patch = $patch.title
ApprovalAction = "Declined"
}
}
}
}
}
function Approve-WSUSUpdate {
<#
.SYNOPSIS
Approves a WSUS update for a specific group with an optional deadline.
.DESCRIPTION
Approves a WSUS update for a specific group with an optional deadline.
.PARAMETER InputObject
Update object that is being approved.
.PARAMETER Update
Name of update being approved.
.PARAMETER Group
Name of group which will receive the update.
.PARAMETER Deadline
Optional deadline for client to install patch.
.PARAMETER Action
Type of approval action to take on update. Accepted values are Install, Approve, Uninstall and NotApproved
.NOTES
Name: Approve-WSUSUpdate
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Approve-WSUSUpdate -update "KB979906" -Group "Domain Servers" -Action Install
Description
-----------
This command will approve all updates with the KnowledgeBase number of KB979906 for the 'Domain Servers' group and
the action command of 'Install'.
.EXAMPLE
Approve-WSUSUpdate -update "KB979906" -Group "Domain Servers" -Action Install -Deadline (get-Date).AddDays(3)
Description
-----------
This command will approve all updates with the KnowledgeBase number of KB979906 for the 'Domain Servers' group and
the action command of 'Install' and sets a deadline for 3 days from when this command is run.
.EXAMPLE
Get-WSUSUpdate -Update "KB979906" | Approve-WSUSUpdate -Group "Domain Servers" -Action Install
Description
-----------
This command will take the collection of objects from the Get-WSUSUpdate command and then approve all updates for
the 'Domain Servers' group and the action command of 'Install'.
#>
[cmdletbinding(
DefaultParameterSetName = 'string',
ConfirmImpact = 'low',
SupportsShouldProcess = $True
)]
Param(
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = 'collection',
ValueFromPipeline = $True)]
[system.object]
[ValidateNotNullOrEmpty()]
$InputObject,
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = 'string',
ValueFromPipeline = $False)]
[string]$Update,
[Parameter(
Mandatory = $True,
Position = 1,
ParameterSetName = '',
ValueFromPipeline = $False)]
[string]
[ValidateSet("Install", "All", "NotApproved","Uninstall")]
$Action,
[Parameter(
Mandatory = $True,
Position = 2,
ParameterSetName = '',
ValueFromPipeline = $False)]
[string]$Group,
[Parameter(
Mandatory = $False,
Position = 3,
ParameterSetName = '',
ValueFromPipeline = $False)]
[datetime]$Deadline
)
Begin {
#Define the actions available
Write-Verbose "Defining available approval actions"
$Install = [Microsoft.UpdateServices.Administration.UpdateApprovalAction]::Install
$All = [Microsoft.UpdateServices.Administration.UpdateApprovalAction]::All
$NotApproved = [Microsoft.UpdateServices.Administration.UpdateApprovalAction]::NotApproved
$Uninstall = [Microsoft.UpdateServices.Administration.UpdateApprovalAction]::Uninstall
#Search for group specified
Write-Verbose "Searching for group"
$targetgroup = Get-WSUSGroup -name $group
If (!$targetgroup) {
Write-Error "Group $group does not exist in WSUS!"
Break
}
}
Process {
#Perform appropriate action based on Parameter set name
Switch ($pscmdlet.ParameterSetName) {
"collection" {
Write-Verbose "Using 'Collection' set name"
#Change the variable that will hold the objects
$patches = $inputobject
}
"string" {
Write-Verbose "Using 'String' set name"
#Search for updates
Write-Verbose "Searching for update/s"
$patches = Get-WSUSUpdate -update $update
If (!$patches) {
Write-Error "Update $update could not be found in WSUS!"
Break
}
}
}
ForEach ($patch in $patches) {
#Determine if Deadline is required
If ($deadline) {
Write-Verbose "Approving update with a deadline."
If ($pscmdlet.ShouldProcess($($patch.title))) {
#Create the computer target group
$patch.Approve($action,$targetgroup,$deadline) | out-null
#Print out report of what was approved
New-Object PSObject -Property @{
Patch = $patch.title
TargetGroup = $group
ApprovalAction = $action
Deadline = "$($deadline)"
}
}
}
Else {
#Approve the patch
Write-Verbose "Approving update without a deadline."
If ($pscmdlet.ShouldProcess($($patch.title))) {
#Create the computer target group
$patch.Approve($action,$targetgroup) | out-null
#Print out report of what was approved
New-Object PSObject -Property @{
Patch = $patch.title
TargetGroup = $group
ApprovalAction = $action
}
}
}
}
}
}
function Get-WSUSGroup {
<#
.SYNOPSIS
Retrieves specific WSUS target group.
.DESCRIPTION
Retrieves specific WSUS target group.
.PARAMETER Name
Name of group to search for. No wildcards allowed.
.PARAMETER Id
GUID of group to search for. No wildcards allowed.
.NOTES
Name: Get-WSUSGroups
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Get-WSUSGroup -name "Domain Servers"
Description
-----------
This command will search for the group and display the information for Domain Servers"
.EXAMPLE
Get-WSUSGroup -ID "0b5ba818-021e-4238-8098-7245b0f90557"
Description
-----------
This command will search for the group and display the information for the WSUS
group guid 0b5ba818-021e-4238-8098-7245b0f90557"
#>
[cmdletbinding(
DefaultParameterSetName = 'name',
ConfirmImpact = 'low',
SupportsShouldProcess = $True
)]
Param(
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = 'name',
ValueFromPipeline = $False)]
[string]$Name,
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = 'id',
ValueFromPipeline = $False)]
[string]$Id
)
Switch ($pscmdlet.ParameterSetName) {
"name" {$wsus.GetComputerTargetGroups() | ? {$_.name -eq $name}}
"id" {$wsus.GetComputerTargetGroups() | ? {$_.id -eq $id}}
}
}
function Remove-WSUSUpdate {
<#
.SYNOPSIS
Removes an update on WSUS.
.DESCRIPTION
Removes an update on WSUS. Use of the -whatif is advised to be sure you are declining the right patch or patches.
.PARAMETER Update
Name of update being removed.
.NOTES
Name: Remove-WSUSUpdate
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Remove-WSUSUpdate -update "KB986569"
Description
-----------
This command will remove all instances of KB986569 from WSUS.
#>
[cmdletbinding(
DefaultParameterSetName = 'update',
ConfirmImpact = 'low',
SupportsShouldProcess = $True
)]
Param(
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = 'update',
ValueFromPipeline = $True)]
[string]$Update
)
Begin {
#Gather all updates from given information
Write-Verbose "Searching for updates"
$patches = Get-WSUSUpdate -update $update
}
Process {
ForEach ($patch in $patches) {
#Storing update guid
$guid = ($patch.id).updateid
If ($pscmdlet.ShouldProcess($($patch.title))) {
$wsus.DeleteUpdate($id,$True)
"$($patch.title) has been deleted from WSUS"
}
}
}
}
function Stop-WSUSDownloads {
<#
.SYNOPSIS
Cancels all current WSUS downloads.
.DESCRIPTION
Cancels all current WSUS downloads.
.NOTES
Name: Stop-WSUSDownloads
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Stop-WSUSDownloads
Description
-----------
This command will stop all updates being downloaded to the WSUS server.
#>
[cmdletbinding(
DefaultParameterSetName = 'update',
ConfirmImpact = 'low',
SupportsShouldProcess = $True
)]
Param()
#Cancel all downloads running on WSUS
If ($pscmdlet.ShouldProcess($($wsus.name))) {
$wsus.CancelAllDownloads()
"Downloads have been cancelled."
}
}
function Resume-WSUSDownloads {
<#
.SYNOPSIS
Resumes all current WSUS downloads.
.DESCRIPTION
Resumes all current WSUS downloads that had been cancelled.
.NOTES
Name: Resume-WSUSDownloads
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Resume-WSUSDownloads
Description
-----------
This command will resume the downloading of updates to the WSUS server.
#>
[cmdletbinding(
DefaultParameterSetName = 'update',
ConfirmImpact = 'low',
SupportsShouldProcess = $True
)]
Param()
#Cancel all downloads running on WSUS
If ($pscmdlet.ShouldProcess($($wsus.name))) {
$wsus.ResumeAllDownloads()
"Downloads have been resumed."
}
}
function Stop-WSUSUpdateDownload {
<#
.SYNOPSIS
Stops update download after approval.
.DESCRIPTION
Stops update download after approval.
.PARAMETER update
Name of update to cancel download.
.NOTES
Name: Stop-WSUSUpdateDownload
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Stop-WSUSUpdateDownload -update "KB965896"
Description
-----------
This command will cancel the download of update KB956896.
#>
[cmdletbinding(
DefaultParameterSetName = 'update',
ConfirmImpact = 'low',
SupportsShouldProcess = $True
)]
Param(
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = 'update',
ValueFromPipeline = $True)]
[string]$update
)
Begin {
#Gather all updates from given information
Write-Verbose "Searching for updates"
$patches = Get-WSUSUpdate -update $update
}
Process {
If ($patches) {
ForEach ($patch in $patches) {
Write-Verbose "Cancelling update download"
If ($pscmdlet.ShouldProcess($($patch.title))) {
$patch.CancelDownload()
"$($patch.title) download has been cancelled."
}
}
}
Else {
Write-Warning "No patches found that need downloading cancelled."
}
}
}
function Resume-WSUSUpdateDownload {
<#
.SYNOPSIS
Resumes previously cancelled update download after approval.
.DESCRIPTION
Resumes previously cancelled update download after approval.
.PARAMETER Update
Name of cancelled update download to resume download.
.NOTES
Name: Resume-WSUSUpdateDownload
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Resume-WSUSUpdateDownload -update "KB965896"
Description
-----------
This command will resume the download of update KB956896 that was previously cancelled.
#>
[cmdletbinding(
DefaultParameterSetName = 'update',
ConfirmImpact = 'low',
SupportsShouldProcess = $True
)]
Param(
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = 'update',
ValueFromPipeline = $True)]
[string]$Update
)
Begin {
#Gather all updates from given information
Write-Verbose "Searching for updates"
$patches = Get-WSUSUpdate -update $update
}
Process {
If ($patches) {
ForEach ($patch in $patches) {
Write-Verbose "Resuming update download"
If ($pscmdlet.ShouldProcess($($patch.title))) {
$patch.ResumeDownload()
"$($patch.title) download has been resumed."
}
}
}
Else {
Write-Warning "No patches found needing to resume download!"
}
}
}
function Start-WSUSCleanup {
<#
.SYNOPSIS
Performs a cleanup on WSUS based on user inputs.
.DESCRIPTION
Performs a cleanup on WSUS based on user inputs.
.PARAMETER DeclineSupersededUpdates
Declined Superseded Updates will be removed.
.PARAMETER DeclineExpiredUpdates
Expired updates should be declined.
.PARAMETER CleanupObsoleteUpdates
Delete obsolete updates from the database.
.PARAMETER CompressUpdates
Obsolete revisions to updates should be deleted from the database.
.PARAMETER CleanupObsoleteComputers
Delete obsolete computers from the database.
.PARAMETER CleanupUnneededContentFiles
Delete unneeded update files.
.NOTES
Name: Start-WSUSCleanup
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Start-WSUSCleanup -CompressUpdates -CleanupObsoleteComputers
Description
-----------
This command will run the WSUS cleanup wizard and delete obsolete computers from the database and delete obsolete update
revisions from the database.
.EXAMPLE
Start-WSUSCleanup -CompressUpdates -CleanupObsoleteComputers -DeclineExpiredUpdates -CleanupObsoleteUpdates -CleanupUnneededContentFiles
Description
-----------
This command performs a full WSUS cleanup against the database.
#>
[cmdletbinding(
DefaultParameterSetName = 'cleanup',
ConfirmImpact = 'low',
SupportsShouldProcess = $True
)]
Param(
[Parameter(
Mandatory = $False,
Position = 0,
ParameterSetName = 'cleanup',
ValueFromPipeline = $False)]
[switch]$DeclineSupersededUpdates,
[Parameter(
Mandatory = $False,
Position = 1,
ParameterSetName = 'cleanup',
ValueFromPipeline = $False)]
[switch]$DeclineExpiredUpdates,
[Parameter(
Mandatory = $False,
Position = 2,
ParameterSetName = 'cleanup',
ValueFromPipeline = $False)]
[switch]$CleanupObsoleteUpdates,
[Parameter(
Mandatory = $False,
Position = 3,
ParameterSetName = 'cleanup',
ValueFromPipeline = $False)]
[switch]$CompressUpdates,
[Parameter(
Mandatory = $False,
Position = 4,
ParameterSetName = 'cleanup',
ValueFromPipeline = $False)]
[switch]$CleanupObsoleteComputers,
[Parameter(
Mandatory = $False,
Position = 5,
ParameterSetName = 'cleanup',
ValueFromPipeline = $False)]
[switch]$CleanupUnneededContentFiles
)
Begin {
#Create cleanup scope
$cleanScope = new-object Microsoft.UpdateServices.Administration.CleanupScope
#Create cleanup manager object
$cleanup = $wsus.GetCleanupManager()
#Determine what will be in the scope
If ($DeclineSupersededUpdates) {
$cleanScope.DeclineSupersededUpdates = $True
}
If ($DeclineExpiredUpdates) {
$cleanScope.DeclineExpiredUpdates = $True
}
If ($CleanupObsoleteUpdates) {
$cleanScope.CleanupObsoleteUpdates = $True
}
If ($CompressUpdates) {
$cleanScope.CompressUpdates = $True
}
If ($CleanupObsoleteComputers) {
$cleanScope.CleanupObsoleteComputers = $True
}
If ($CleanupUnneededContentFiles) {
$cleanScope.CleanupUnneededContentFiles = $True
}
}
Process {
Write-Host "Beginning cleanup"
If ($pscmdlet.ShouldProcess($($wsus.name))) {
$cleanup.PerformCleanup($cleanScope)
}
}
}
function Get-WSUSChildServers {
<#
.SYNOPSIS
Retrieves all WSUS child servers.
.DESCRIPTION
Retrieves all WSUS child servers.
.NOTES
Name: Get-WSUSChildServers
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Get-WSUSChildServers
Description
-----------
This command will display all of the Child WSUS servers.
#>
[cmdletbinding()]
Param ()
#Gather all child servers in WSUS
$wsus.GetChildServers()
}
function Get-WSUSDownstreamServers {
<#
.SYNOPSIS
Retrieves all WSUS downstream servers.
.DESCRIPTION
Retrieves all WSUS downstream servers.
.NOTES
Name: Get-WSUSDownstreamServers
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Get-WSUSDownstreamServers
Description
-----------
This command will display a list of all of the downstream WSUS servers.
#>
[cmdletbinding()]
Param ()
#Gather all child servers in WSUS
$wsus.GetDownstreamServers()
}
function Get-WSUSContentDownloadProgress {
<#
.SYNOPSIS
Retrieves the progress of currently downloading updates. Displayed in bytes downloaded.
.DESCRIPTION
Retrieves the progress of currently downloading updates. Displayed in bytes downloaded.
.PARAMETER Monitor
Runs a background job to monitor currently running content download and notifies user when completed.
.NOTES
Name: Get-WSUSContentDownloadProgress
Author: Boe Prox
DateCreated: 24SEPT2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Get-WSUSContentDownloadProgress
Description
-----------
This command will display the current progress of the content download.
.EXAMPLE
Get-WSUSContentDownloadProgress -monitor
Description
-----------
This command will create a background job that will monitor the progress and alert the user via pop-up message that
the download has been completed.
#>
[cmdletbinding()]
Param (
[Parameter(
Mandatory = $False,
Position = 0,
ParameterSetName = 'monitor',
ValueFromPipeline = $False)]
[switch]$Monitor
)
If ($monitor) {
#Stop and remove same jobs if existing
$job = Get-Job
If ($job) {
$job = Get-Job -Name "WSUSSyncProgressMonitor"
}
If ($job) {
Get-Job -Name "WSUSContentProgressMonitor" | Stop-Job
Get-Job -Name "WSUSContentProgressMonitor" | Remove-Job
}
Start-Job -Name "WSUSContentProgressMonitor" -ArgumentList $wsus -ScriptBlock {
Param (
$wsus
)
#Load required assemblies for message window
[void] [System.Reflection.Assembly]::LoadWithPartialName(“System.Windows.Forms”)
$progress = $wsus.GetContentDownloadProgress()
While ($progress.TotalBytesToDownload -ne $progress.DownloadedBytes) {
$null
}
[System.Windows.Forms.MessageBox]::Show("Content download has been completed on WSUS",”Information”)
} | Out-Null
}
Else {
#Gather all child servers in WSUS
$wsus.GetContentDownloadProgress()
}
}
function Remove-WSUSClient {
<#
.SYNOPSIS
Removes client from WSUS.
.DESCRIPTION
Removes client from WSUS.
.PARAMETER Computer
Name of the client to remove from WSUS.
.PARAMETER InputObject
Computer object that is being removed.
.NOTES
Name: Remove-WSUSClient
Author: Boe Prox
DateCreated: 12NOV2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Remove-WSUSClient -computer "server1"
Description
-----------
This command will remove 'server1' from WSUS.
.EXAMPLE
Get-WSUSClient -computer "server1" | Remove-WSUSClient
Description
-----------
This command will remove 'server1' from WSUS.
.EXAMPLE
Get-WSUSClient -computer "servers" | % {Remove-WSUSClient -inputobject $_}
Description
-----------
This command will remove multiple servers from WSUS.
#>
[cmdletbinding(
DefaultParameterSetName = 'collection',
ConfirmImpact = 'low',
SupportsShouldProcess = $True
)]
Param(
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = 'string',
ValueFromPipeline = $True)]
[string]$Computer,
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = 'collection',
ValueFromPipeline = $True)]
[system.object]
[ValidateNotNullOrEmpty()]
$InputObject
)
$ErrorActionPreference = 'continue'
Switch ($pscmdlet.ParameterSetName) {
"string" {
Write-Verbose "String parameter"
#Retrieve computer in WSUS
Try {
Write-Verbose "Searching for computer"
$client = $wsus.SearchComputerTargets($computer)
}
Catch {
Write-Error "Unable to retrieve $($computer) from database."
}
}
"Collection" {
Write-Verbose "Collection parameter"
$client = $inputobject
}
}
#Remove client from WSUS
If ($pscmdlet.ShouldProcess($computer)) {
Try {
Write-Verbose "Removing computer from WSUS"
$client | % -process {$_.Delete()}
Write-Host -fore Green "$($Client.FullDomainName) removed from WSUS"
}
Catch {
Write-Error "Unable to remove $($client.fulldomainname) from WSUS."
}
}
}
function Get-WSUSClientGroupMembership {
<#
.SYNOPSIS
Lists all Target Groups that a client is a member of in WSUS.
.DESCRIPTION
Lists all Target Groups that a client is a member of in WSUS.
.PARAMETER Computer
Name of the client to check group membership.
.PARAMETER InputObject
Computer object being used to check group membership.
.NOTES
Name: Get-WSUSClientGroupMembership
Author: Boe Prox
DateCreated: 12NOV2010
.LINK
https://boeprox.wordpress.org
.EXAMPLE
Get-WSUSClientGroupMembership -computer "server1"
Description
-----------
This command will retrieve the group membership/s of 'server1'.
.EXAMPLE
Get-WSUSClient -computer "server1" | Get-WSUSClientGroupMembership
Description
-----------
This command will retrieve the group membership/s of 'server1'.
.EXAMPLE
Get-WSUSClient -computer "servers" | % {Get-WSUSClientGroupMembership -inputobject $_}
Description
-----------
This command will retrieve the group membership/s of each server.
#>
[cmdletbinding(
DefaultParameterSetName = 'collection',
ConfirmImpact = 'low',
SupportsShouldProcess = $True
)]
Param(
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = 'string',
ValueFromPipeline = $True)]
[string]$Computer,
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = 'collection',
ValueFromPipeline = $True)]
[system.object]
[ValidateNotNullOrEmpty()]
$InputObject
)
$ErrorActionPreference = 'continue'
Switch ($pscmdlet.ParameterSetName) {
"string" {
Write-Verbose "String parameter"
#Retrieve computer in WSUS
Try {
Write-Verbose "Searching for computer"
$client = $wsus.SearchComputerTargets($computer)
}
Catch {
Write-Error "Unable to retrieve $($computer) from database."
}
}
"Collection" {
Write-Verbose "Collection parameter"
$client = $inputobject
}
}
#List group membership of client
$client | % -process {$_.GetComputerTargetGroups()}
}

Trying to run this on my WSUS server (Server 2012 R2) and it won’t connect no matter what server name I give it…
Any thoughts! I am desperately trying to cancel some downloads that cause the WSUS MMC console to crash when I try to cancel the downloads there.
Is there any way to reset updates that have been approved to not approved using this? I’ve seen a blanket decline option but nothing that gives a “un-approve updates for group/collection B only”
Does anyone know how can I change the target group of results? I mean, all results that I obtaine with Posh WSUS , just showing for an specific group and I want all computers. I will really appreciate your help…
I have been using this module for years now and its a pretty neat and useful too. Thanks for your effort and time and sharing this.
Boe, I am trying to schedule a report that would show that same report for ‘Computer Tabular Status Report for Approved Updates’ but I can not seem to figure out as the result is always the same to just ”Computer Tabular Status Report”. When time permits, can you help check and let me know the right combination to get the right output? Thanks a lot!
Here is my code:
Import-Module “D:\PoshWSUS”
$WSUSServer = Connect-PoshWSUSServer -WsusServer “WSUSServer” -Port 8530
$Result = $Null; $Result = @()
$FQDNs = Get-PoshWSUSClientsInGroup -Name “Test Group” | % {$.FullDomainName}
Foreach ($FQDN in $FQDNs){
$ComputerScope = New-poshWSUSComputerScope -NameIncludes $FQDN.split(“.”)[0]
$UpdateScope = New-poshWSUSUpdateScope -ApprovedStates Any -UpdateApprovalActions Install -IncludedInstallationStates All
$Result += Get-PoshWSUSUpdateSummaryPerClient -ComputerScope $ComputerScope -UpdateScope $UpdateScope
}
$Result | Sort Computer | Select Computer,@{n=’Needed’;e={$.NeededCount}},InstalledCount,NotApplicableCount,
@{n='InstalledAndNotApplicable';e={$_.InstalledCount + $_.NotApplicableCount}},UnknownCount,FailedCount,@{n=’PendingReboot’;e={$_.InstalledPendingRebootCount}},DownloadedCount,LastUpdated | ft -auto
An interesting and promising article for some broken WSUS systems I’m working with. Do you know where I can locate a copy of the module that contains these commands (wsusadmin-module.psm1) for WSUS 3.0 SP2? All references I can find point me to PoshWSUS, which has different commands and syntax.
Thanks!
Pingback: WSUS Administrator Module Aus der IT – Praxis…
I work at a datacenter and it works great for one of my customers but for another when I do connect-poshwsusserver computername I get error Unable to connect to computername!
I haven’t found any useful help articles online.
Are they using the same port with WSUS? If not you will need timo specify the different port using-Port.
Hello Boe,
I’m having the same issue. My server uses 8530/8531 and even when I specify these ports the message is the same “WARNING: Unbale to connect to …”
Thank oyu.
I had the same issue and found I had to add
before import-module…
Pingback: Installing and Configuring WSUS with Powershell | smsagent
Well done.
Could you tell me if there is any way to get wsus update with parametar of approval/decline date/time?
Thank you
Loved it. Very useful.Thanks!
Pingback: PoshWSUS on Codeplex | Server Ninjas
Hi,
very nice and useful module ! excellent job 🙂
quick idea/suggestion if you are interested in…
Could be useful to check the approval status per KB to know in which WSUS groups the KB has been approved or not…
let me know your thoughts
Cheers,
Michael
Some problems with ”
Get-Wsusclientgroupmembership -Computer “$servername” ”
If the servename is identical with some characters you get to much information/groups from all server.
Example:
Servername is a)serverastest and b)serverastest2.msds.insite
$servername=serverastest
First you get all information for both server.
If you set $servername=servertest2.msds.insite you got only the information about this server.
I think the function doesn’t search the servername. The function works with wildcards as a string and not with the correct servername…
Can you help me for a better version, please.
I will add this to my list of things to do for the module and see what I can do about this. Thanks!
Pingback: WSUS and Powershell « The Wonders Never Cease
Pingback: Some cool PowerShell modules | Dalle & DXter
Pingback: Episode 133 – Shane Hoey in Australia is Paging Dr. Scripto « PowerScripting Podcast
Truly amazing site ! Have a look at it !
I’d recommend splitting this module up into different source files. The main module file could be the “installer” for it, referencing the “real” source files using dot-sourcing.
I used this method in the current module I’m working on, and it works great. Besides making module maintenance easier, it also adds a level of professionalism to the module, rather than sticking everything inside a single file.
Cheers,
Trevor Sullivan (@pcgeek86)
Interesting. I will definitely look into that for the next version. Thanks for the good information!
I’d also suggest publishing it on CodePlex :]
Wow looks promising, I will definitely give it a try.