INTRODUCTION

As part of a clean up task at a customer I had to create a script which would move Software Updates from the latest created Software Update Group (SUG) to a yearly, consolidated one.

MY RECOMMENDATIONS

Previously I have automatically created a new Software Update Group (SUG) when the monthly Patch Tuesday Automatic Deployment Rule has been evaluated.

The reason why you would want to do this is that there is a soft limit of 1000 patches per Software Update Group. I can’t really say what will happen if you exceed this amount, but it is a general recommendatio not to do so.

SOFTWARE UPDATE GROUP CLEANUP

Cleaning up Software Update Groups (SUGs) is important. I have seen examples where a new Software Update Group has been created each time an Automatic Deployment Rule (ADR) has been evaluated. This is usually not an issue, but in this case, it only contained Windows Defender definition updates.

SOLUTION

WHY SHOULD I USE IT?

If you have configured an Automatic Deployment Rule (ADR) to create a new Software Update Group upon every new evaluation, you will end up with quite a lot of Software Update Groups.

At the end of the year I have previously consolidated all Software Updates for that given year in to a yearly Software Update Group called All Windows Client Updates 2018 or similar.
When doing this I have used Nickolaj Andersen’s excellent tool to create Software Update Groups.

HOW DOES IT WORK?

If you want to move a Software Update between different Software Update Groups, you don’t actually move them, but rather change the membership.

The script that I have provided will take the latest created Software Update Group and add those members to a defined Software Update Group.

THE SCRIPT

Below is the script I have created for editing the membership of a Software Update Group.

<#
.SYNOPSIS
This script will add all updates from the latest Software Update Group to a defined Software Update Group.
    
.DESCRIPTION
This script will add all updates from the latest Software Update Group to a defined Software Update Group.

Author: Daniel Classon (www.danielclasson.com)
Version: 1.0
Date: 2018-12-18
    
.EXAMPLE
.\Add-SUGMembers -DestinationSUG SUG1
This will add all updates contained in the latest Software Updates Group to SUG1.
    
.DISCLAIMER
All scripts and other powershell references are offered AS IS with no warranty.
These script and functions are tested in my environment and it is recommended that you test these scripts in a test environment before using in your production environment.
#>


PARAM(
    [string]$DestinationSUG
    )

#Load SCCM Powershell module
Try {
    Import-Module (Join-Path $(Split-Path $env:SMS_ADMIN_UI_PATH) ConfigurationManager.psd1) -ErrorAction Stop
}
Catch [System.UnauthorizedAccessException] {
    Write-Warning -Message "Access denied" ; break
}
Catch [System.Exception] {
    Write-Warning "Unable to load the Configuration Manager Powershell module from $env:SMS_ADMIN_UI_PATH" ; break
}

#Set current drive to SCCM drive

$SiteCode = Get-PSDrive -PSProvider CMSITE
Set-Location -Path "$($SiteCode.Name):\"

Function Write-Log
{
 
    PARAM(
        [String]$Message,
        [int]$Severity,
        [string]$Component
    )
        $LogPath = $PSScriptRoot
        $TimeZoneBias = Get-WMIObject -Query "Select Bias from Win32_TimeZone"
        $Date= Get-Date -Format "HH:mm:ss.fff"
        $Date2= Get-Date -Format "MM-dd-yyyy"
        $Type=1
         
        "<![LOG[$Message]LOG]!><time=$([char]34)$Date$($TimeZoneBias.bias)$([char]34) date=$([char]34)$date2$([char]34) component=$([char]34)$Component$([char]34) context=$([char]34)$([char]34) type=$([char]34)$Severity$([char]34) thread=$([char]34)$([char]34) file=$([char]34)$([char]34)>"| Out-File -FilePath "$LogPath\Add-SUGMembers.log" -Append -NoClobber -Encoding default
}

#Change membership of Software Update to new Software Update Group

$LatestSUG = Get-CMSoftwareUpdateGroup | Select-Object LocalizedDisplayName,DateCreated | Sort-Object DateCreated | Select-Object -Last 1 
$Updates = Get-CMSoftwareUpdate -UpdateGroupName $LatestSUG -Fast
$Count = 0

Foreach ($Update in $Updates) {
    $Count++
    Try {
        Add-CMSoftwareUpdateToGroup -SoftwareUpdateId $($Update.CI_ID) -SoftwareUpdateGroupId $($DestinationSUG.CI_ID)
        Write-Progress -Activity "Adding $($Update.LocalizedDisplayName) to $($DestinationSUG.LocalizedDisplayName)" -Status "Adding $Count of $($Updates.Count) updates to $($SourceSUG.LocalizedDisplayName)" -PercentComplete ($Count / $Updates.count * 100)
        Write-Log -Message "Adding $($Update.LocalizedDisplayName) to $($DestinationSUG.LocalizedDisplayName)" -Severity 1 -Component "Add SU to SUG"
    }
    Catch {
        Write Warning "$_.Exception.Message"
        Write-Log -Message "$_.Exception.Message" -Severity 3 -Component "Add SU to SUG"
    }
}
Set-Location $PSScriptRoot

CONCLUSION

Using the mentioned script will help you with keeping tack of your Software Update Groups. Great!

REFERENCES

Microsoft Docs – Add Software Updates to a Software Update Group

RELATED POSTS