WSUS maintenance (Automate Software Update Maint in ConfigMgr) - PandaM0nium/MEMC GitHub Wiki

Invoke-DGASoftwareUpdateMaintenance.ps1

Capability

  • Detect if a synchronization is occurring and wait for success before resuming.
  • Decline superseded updates.
  • Decline updates by a list of titles.
  • Decline updates based on external plugin scripts.
  • Output a comma-delimited list of declined updates.
  • Run the WSUS Cleanup Wizard.
  • Initiate a software update synchronization.
  • Remove expired and declined updates from software update groups.
  • Delete software update groups that have no updates.
  • Combine software update groups into yearly groups.
  • Set the maximum run time for updates by title.
  • Remove unneeded files from the deployment package source folder.
  • Update the deployment packages used by ADRs either monthly or yearly.
  • Directly call the stored procedures to delete obsolete updates.
  • Add crucial indexes that make WSUS run faster overall.
  • Delete updates that have been declined from the WSUS database entirely.

Currently this script must be ran on the primary site server as it makes certain queries to WMI classes that only reside there. The user running this is going to need a lot of permissions to a bunch of things and the primary site’s system account is perfect on that front.

The script is designed to be ran between the time your Software Update Point(s) sync updates from Microsoft and when your ADRs run. This allows the plugin scripts to preemptively decline updates that ADR selection can’t properly filter. Nothing prevents you from running it any time you like of course. In fact, if you have not been maintaining updates I recommend running this manually outside of your normal patching cycle first.

Requirements

  • The WSUS console and cmdlets must be installed.
  • The Configuration Manager console and cmdlets must be installed.
  • The script must be ran on or from the primary site server.
  • The user needs to be part of the WSUS Administrators group on SUPs.
  • The user needs full access to the deployment package source folders.
  • The user needs the appropriate rights in SCCM to modify the objects your chosen parameters will impact.

Deployment

Copy Invoke-DGASoftwareUpdateMaintenance to file share and local location on ConfigMgr server

Create a Status Filter rule that triggers based on the update synchronization ending successfully.

  Create a status rule that runs a commmand when the SMS_WSUS_SYNC_MANAGER component sends a status the message ID 6702 (https://docs.microsoft.com/en-us/configmgr/core/servers/manage/use-alerts-and-the-status-system#to-create-a-status-filter-rule)

  Administration --> Site Configuration --> Sites --> Home Ribbon --> Status Filter Rules

  Create New Status Filter Rule with the wizard --> Name: Run Software Update maintenance, Component: SMS_WSUS_SYNC_MANAGER, Message ID: 6702

  Specify Action to run a program: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -executionpolicy bypass -noninteractive -File \\#PATH TO SCRIPT FOLDER#\Invoke-DGASoftwareUpdateMaintenance.ps1

Move required plugin from Invoke-DGASoftwareUpdateMaintenance\Plugins\Disabled to Invoke-DGASoftwareUpdateMaintenance\Plugin

Modify config.ini file to reflect the required action - The script that run without parameter will use config.ini in the root folder for parameters selection. Make sure to comment out WhatIfPreferene at the end of the ini file.

  ;Example configuration file
  ;Note-You will need to remove the WhatIfPreference configuration before changes to your environment will be made.

  CleanSources
  CleanSUGs
  ;CombineSUGs=3
  DeclineByPlugins 
  DeclineByTitle=@('*Security Only*','*Preview of*','(Preview)*','*Itanium*','*ia64*','*Beta*','*Version Next*')
  ;DeclineLastLevelOnly
  DeclineSuperseded
  DeleteDeclined
  ;ExcludeByProduct=@('*name*','*name*')
  ;ExcludeByTitle=@('*name*','*name*')
  ;ExclusionPeriod=3
  ;FirstRun
  ;Force
  ;IncludeByProduct=@('*name*','*name*')
  LogFile=\\ar-fs01\Domain_FileShare\Share_resources\Logs\WSUS_Maint\Invoke-DGASoftwareUpdateMaintenance.log
  MaxLogSize=2621440
  MaxUpdateRuntime=@{'*Cumulative Update for Windows 10*'=90;'*Security Monthly Quality Rollup For Windows*'=90;'*Security and Quality Rollup for .NET*'=90}
  RemoveEmptySUGs
  ReSyncUpdates
  RunCleanUpWizard
  ;SiteCode=ARR
  ;StandAloneWSUS=MyWSUSserver.contoso.com
  ;StandAloneWSUSPort=8530
  ;StandAloneWSUSSSL=$False
  ;SyncLeadTime=5
   UpdateADRDeploymentPackages=Yearly
   UpdateListOutputFile
   UseCustomIndexes
  ;WhatIfPreference

Parameters list

-CleanSources [switch] Loop through the software update Deployment Packages and remove any sub-folders whose name does not match a GUID of an update in the package.

-CleanSUGs [switch] Loop through every Software Update Group and remove any expired or newly declined updates.

-ConfigFile [string] Path to an INI file containing the configuration you wish used. If the script is ran with zero parameters then the script will default to using a configuration file named config.ini in the root of the script directory.

-CombineSUGs [int] Combine Software Updates Groups so that only the provided number of groups exist per Automatic Deployment Rule. The first group created for a given year will be renamed by having its timestamp truncated to just its year and will have the remaining groups updates added to it.

-DeclineByPlugins [switch] Loop through every PowerShell script file (.PS1) in the Plugins folder relative to the script and call its Invoke-SelectUpdatesPlugin function. This allows users to decline updates using whatever logic they desire. The download includes some examples as well as a template to build from. In order to use the provided plugin scripts you will need to copy them from the Disabled folder into the root of the Plugins folder. Some of them need to be edited before they are ran. See the Plugin Script section above above for more details.

-DeclineByTitle [string[]] Provide an array of titles that will be used to decline updates in WSUS. Wildcards are of course supported. Note that passing in an array via the command line is a bit tricky and you must use the -command option when using this parameter. See the example above for how to do this.

-DeclineLastLevelOnly [switch] Only declines updates that do not supersede other updates. Must be used with the DeclineSuperseded parameter. Honestly, I have no idea why you want to use this but I put this in for completeness as compared to other scripts.

-DeclineSuperseded [switch] Declines updates that are superseded in WSUS. Refer to the DeclineLastLevelOnly and ExclusionPeriod parameters for options regarding which superseded update you decline.

-DeleteDeclined [switch] When this switch is used the script will track the date that it declines updates using a datafile stored in the script’s directory. When the update has been declined for longer than the configured ExclusionPeriod the script will delete the update from WSUS entirely using the WSUS API calls. This can drastically reduce the amount of data stored in the WSUS database.

-ExcludeByProduct [string[]] An array of strings that can be used to exclude updates from certain products from being declined regardless of the method used to decline them.

-ExcludeByTitle [string[]] An array of strings that can be used to exclude updates from being decline regardless of the method used to decline them.

-ExclusionPeriod [int] An integer that controls how many months to keep updates before declining and/or deleting them. When declining updates this is based on the creation date of the superseding update rather than the superseded update. When deleting updates this is based on when the script declined the updates. This parameter must be used with the DeclineSuperseded or DeleteDeclined parameters and only impacts those two features. If this parameter is not defined then the script will use the exclusion period configured in the Software Update component for declining superseded updates or default to 3 if used in WSUSStandalone mode.

-FirstRun [switch] If your environment or a the environment of a close ‘friend’ has never been maintained and the script times out when ran then run the script manually one time using this option. It will connect directly to the WSUS database (SUSDB) and get a list of obsolete updates using the spGetObsoleteUpdatesToCleanup stored procedure. It then loops through and deletes each one using the spDeleteUpdate stored procedure. This mimics what the WSUS cleanup wizard does but with a 24 hours timeout instead of the default 30 second one. Be aware that this may take hours, days, weeks, or even longer to complete. However, it most likely will complete unlike the wizard. Afterwards you should be able to run the script normally.

-Force [switch] The script creates an empty file in the its directory to mark the last time it ran and will not run again if that file is newer than 24 hours unless the Force parameter is used. Be very very careful with this parameter. If used in conjunction with the ReSyncUpdates parameter as part of a status filter rule you can create a forever loop.

-IncludeByProduct [string[]] An array of string that can be used to define which products to decline updates from. No updates outside of the listed products will be declined.

-LogFile [string] Specify an alternate log file path. By default the script will create the log in the same folder as the script.

-MaxLogSize [int] Specify the maximum size of the log file before it rolls over and rename the current log with the ‘.lo_’ extension. The default is 2 MB.

-MaxUpdateRuntime [hashtable] Provide a hash-table where the keys are titles and the values are the number of minutes to set matching updates’ maximum run-time to. Wildcards are of course supported for the titles. Note that passing in a hash-table via the command line is a bit tricky and you must use the -command option when using this parameter. See the example above for how to do this.

-RemoveCustomIndexes [switch] Remove the custom indexes from the WSUS database if they exist.

-RemoveEmptySUGs [switch] Remove any Software Update Groups that do not contain any software updates. Must be used with the CleanSUGs parameter.

-ReSyncUpdates [switch] Initiate a full Configuration Manager software update synchronization. This will run after the updates have been declined in WSUS and will expire the declined updates in Configuration Manager.

-RunCleanupWizard [switch] Runs the WSUS Cleanup Wizard with all the options selected after declining updates. Even though Configuration Manager includes this feature now I’ve included this for completeness. To be honest, I’m not certain what Configuration Manager is actually doing on this front. I’ve had the built-in feature enabled from day one and yet when I ran this manually in my environments the first cleanup run took 1-2 hours and cleaned up thousands of items. Subsequent runs took minutes. As an added bonus it will write the results to the log file.

-SiteCode [string] Provide the site code of the site you wish to connect to. By default the script will try to identify the site by the PS-Drives available or from the registry. In environments with a CAS this parameter must be provided.

-StandAloneWSUS [string] If you wish to run the script against a stand-alone WSUS server then specify the FQDN of the WSUS server using this parameter. When doing so the script will prevent you from also including parameters that only apply to a Configuration Manager environment.

-StandAloneWSUSSSL [switch] If you specified the StandAloneWSUS parameter you may optionally specify whether to connect via SSL or not. If this parameter is not used the script will try to connect without using SSL.

-StandAloneWSUSPort [int] If you specified the StandAloneWSUS parameter you may optionally specify the port to connect upon. If not specified the port will default to 8531 if the StandAloneWSUSSSL switch is used and 8530 if it is not.

-SyncLeadTime [int] Specifies the number of minutes to wait after a software update synchronization has occurred before continuing script execution. The default is 5 minutes.

-UpdateADRDeploymentPackages [string (‘Yearly’,’Monthly’)] Creates new deployment packages on either a yearly or monthly basis and updates the ADRs to use them. When used, the name of the deployment package and the source folder for the package must end with four digits that represent the desired period. For yearly packages a four-digit year (ex. 2017) must be used and for monthly packages use YYMM (ex. 1710 for October 2017).

-UpdateListOutputFile [string] Specify a file path where the script will output a comma delimited text file listing the details of every update it declines and the reason why it was declined.

-UseCustomIndexes [switch] Check for and if necessary create additional indexes that help run WSUS perform better. This feature is highly recommended and can be crucial to successfully running the FirstRun feature or the WSUS Cleanup Wizard in general. Note, these indexes are not supported by Microsoft.

-WhatIf [switch] Last, but not least, use this to test what the script will do without making any changes. Refer to the log or use the UpdateListOutputFile parameter to output a list of declined updates.