Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
197 lines (170 sloc) 10.1 KB
<#
.SYNOPSIS
Create a Software Update Group containing Software Updates defined by Product and Update Classification between a range of years.
.DESCRIPTION
This script will create a Software Update Group containing Software Updates defined by Product and Update Classification between a range of years.
.PARAMETER SiteServer
Site server where the SMS Provider is installed
.PARAMETER Name
Name of the Software Update Group.
.PARAMETER Products
Define a set of Products.
.PARAMETER UpdateClassifications
Define a set of Update Classifications.
.PARAMETER StartYear
Set the start year from which released or revised patches will be evaluated against when adding to Software Update Group.
.PARAMETER EndYear
Set the end year when released or revised patches will be evaluated against when adding to Software Update Group.
.EXAMPLE
Create a Software Update Groups containing Security Updates and Critical Updates for Windows 7 and Windows 8.1 between 2014 and 2015:
.\New-CMSoftwareUpdateGroupBetweenYear.ps1 -SiteServer CM01 -Name "SUM - Windows Clients - 2014-2015" -Products "Windows 7","Windows 8.1" -UpdateClassifications "Critical Updates","Security Updates" -StartYear 2014 -EndYear 2015 -Verbose
Create a Software Update Groups containing Security Updates and Critical Updates for Windows Server 2012 R2 between 2015 and 2015:
.\New-CMSoftwareUpdateGroupBetweenYear.ps1 -SiteServer CM01 -Name "SUM - Windows Clients - 2014-2015" -Products "Windows Server 2012 R2" -UpdateClassifications "Critical Updates","Security Updates" -StartYear 2015 -EndYear 2015 -Verbose
.NOTES
FileName: New-CMSoftwareUpdateGroupBetweenYear.ps1
Author: Nickolaj Andersen
Contact: @NickolajA
Created: 2016-03-22
Updated: 2016-03-27
Version: 1.0.0
#>
[CmdletBinding(SupportsShouldProcess=$true)]
param(
[parameter(Mandatory=$true, HelpMessage="Site server where the SMS Provider is installed.")]
[ValidateNotNullOrEmpty()]
[ValidateScript({Test-Connection -ComputerName $_ -Count 1 -Quiet})]
[string]$SiteServer,
[parameter(Mandatory=$true, HelpMessage="Name of the Software Update Group.")]
[ValidateNotNullOrEmpty()]
[string]$Name,
[parameter(Mandatory=$true, HelpMessage="Define a set of Products.")]
[ValidateNotNullOrEmpty()]
[ValidateSet("Windows 7", "Windows 8.1", "Windows 10", "Windows 10 LTSB", "Windows Server 2008", "Windows Server 2008 R2", "Windows Server 2012", "Windows Server 2012 R2", "Office 2007", "Office 2010", "Office 2013", "Office 2016", "Office 365 Client")]
[string[]]$Products,
[parameter(Mandatory=$true, HelpMessage="Define a set of Update Classifications.")]
[ValidateNotNullOrEmpty()]
[ValidateSet("Critical Updates", "Security Updates", "Feature Packs", "Updates", "Update Rollups")]
[string[]]$UpdateClassifications,
[parameter(Mandatory=$true, HelpMessage="Set the start year from which released or revised patches will be evaluated against when adding to Software Update Group.")]
[ValidateNotNullOrEmpty()]
[string]$StartYear,
[parameter(Mandatory=$true, HelpMessage="Set the end year when released or revised patches will be evaluated against when adding to Software Update Group.")]
[ValidateNotNullOrEmpty()]
[string]$EndYear
)
Begin {
# Determine SiteCode from WMI
try {
Write-Verbose -Message "Determining Site Code for Site server: '$($SiteServer)'"
$SiteCodeObjects = Get-WmiObject -Namespace "root\SMS" -Class SMS_ProviderLocation -ComputerName $SiteServer -ErrorAction Stop
foreach ($SiteCodeObject in $SiteCodeObjects) {
if ($SiteCodeObject.ProviderForLocalSite -eq $true) {
$SiteCode = $SiteCodeObject.SiteCode
Write-Verbose -Message "Site Code: $($SiteCode)"
}
}
}
catch [System.UnauthorizedAccessException] {
Write-Warning -Message "Access denied" ; break
}
catch [System.Exception] {
Write-Warning -Message "Unable to determine Site Code" ; break
}
}
Process {
# Functions
function New-SoftwareUpdateGroupList {
param(
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$SoftwareUpdateGroupName,
[parameter(Mandatory=$false)]
[System.Collections.ArrayList]$UpdatesList
)
# Create a new SMS_CI_LocalizedProperties instance (embedded object)
$LocalizedProperties = ([WmiClass]"\\$($SiteServer)\root\SMS\site_$($SiteCode):SMS_CI_LocalizedProperties").CreateInstance()
$LocalizedProperties.DisplayName = $SoftwareUpdateGroupName
$LocalizedProperties.Description = "Automatically generated by script"
$LocalizedProperties.LocaleID = 1033
# Create a new SMS_AuthorizationList instance
$AuthorizationListArguments = @{
LocalizedInformation = [array]$LocalizedProperties
}
try {
Set-WmiInstance -Namespace "root\SMS\site_$($SiteCode)" -Class SMS_AuthorizationList -ComputerName $SiteServer -Arguments $AuthorizationListArguments -ErrorAction Stop | Out-Null
Write-Verbose -Message "Successfully created '$($SoftwareUpdateGroupName)' software update group"
}
catch [System.Exception] {
Write-Warning -Message "Unable to create '$($SoftwareUpdateGroupName)' software update group, breaking build operation. Line: $($_.InvocationInfo.ScriptLineNumber)" ; break
}
# Add list of CI_ID's to Software Update Group
$SoftwareUpdateGroup = Get-WmiObject -Namespace "root\SMS\site_$($SiteCode)" -Class SMS_AuthorizationList -ComputerName $SiteServer -Filter "LocalizedDisplayName like '$($SoftwareUpdateGroupName)'" -ErrorAction Stop
if ($SoftwareUpdateGroup -ne $null) {
$SoftwareUpdateGroup.Get()
$SoftwareUpdateGroup.Updates = $UpdatesList
$SoftwareUpdateGroup.Put() | Out-Null
Write-Verbose -Message "Successfully added '$($UpdatesList.Count)' software updates to '$($SoftwareUpdateGroupName)' software update group"
}
}
# Build Software Udates updates classification hash-table
$UpdateClassificationsTable = @{}
$UpdateClassificationObjects = Get-WmiObject -Namespace "root\SMS\site_$($SiteCode)" -Class SMS_CategoryInstance -Filter "CategoryTypeName like 'UpdateClassification'"
foreach ($UpdateClassificationObject in $UpdateClassificationObjects) {
$UpdateClassificationsTable.Add($UpdateClassificationObject.LocalizedCategoryInstanceName, $UpdateClassificationObject.CategoryInstance_UniqueID)
}
# Build Software Udates products hash-table
$ProductsTable = @{}
$ProductObjects = Get-WmiObject -Namespace "root\SMS\site_$($SiteCode)" -Class SMS_CategoryInstance -Filter "CategoryTypeName like 'Product' AND LocalizedCategoryInstanceName not like 'Windows Live' AND LocalizedCategoryInstanceName not like 'Visual Studio 2010 Tools for Office Runtime'"
foreach ($ProductObject in $ProductObjects) {
$ProductsTable.Add($ProductObject.LocalizedCategoryInstanceName, $ProductObject.CategoryInstance_UniqueID)
}
# Construct beginning of Software Updates query
$SoftwareUpdatesQuery = "SELECT SMS_SoftwareUpdate.* FROM SMS_SoftwareUpdate WHERE (SMS_SoftwareUpdate.CI_ID NOT IN (SELECT CI_ID FROM SMS_CIAllCategories WHERE CategoryInstance_UniqueID='UpdateClassification:3689bdc8-b205-4af4-8d4a-a63924c5e9d5'))"
# Construct year part of query
$SoftwareUpdatesQuery = -join @($SoftwareUpdatesQuery, " AND (DateRevised >='01/01/$($StartYear) 00:00:00' AND DateRevised <='12/31/$($EndYear) 00:00:00' )")
# Construct expired updates part of query
$SoftwareUpdatesQuery = -join @($SoftwareUpdatesQuery, " AND (IsExpired ='0' ) AND ")
# Construct Products part of query
$ProductsCount = 0
$SoftwareUpdatesQuery = -join @($SoftwareUpdatesQuery, "( ")
foreach ($Product in $Products) {
$ProductsCount++
if ($ProductsCount -lt $Products.Count) {
$SoftwareUpdatesQuery = -join @($SoftwareUpdatesQuery, "CI_ID in (select CI_ID from SMS_CIAllCategories where CategoryInstance_UniqueID='$($ProductsTable[$Product])') OR ")
}
else {
$SoftwareUpdatesQuery = -join @($SoftwareUpdatesQuery, "CI_ID in (select CI_ID from SMS_CIAllCategories where CategoryInstance_UniqueID='$($ProductsTable[$Product])')")
}
}
$SoftwareUpdatesQuery = -join @($SoftwareUpdatesQuery, " )")
# Construct superseded part of query
$SoftwareUpdatesQuery = -join @($SoftwareUpdatesQuery, " AND (IsSuperseded ='0' ) AND ")
# Construct classification part of query
$UpdateClassificationsCount = 0
$SoftwareUpdatesQuery = -join @($SoftwareUpdatesQuery, "( ")
foreach ($UpdateClassification in $UpdateClassifications) {
$UpdateClassificationsCount++
if ($UpdateClassificationsCount -lt $UpdateClassifications.Count) {
$SoftwareUpdatesQuery = -join @($SoftwareUpdatesQuery, "CI_ID in (select CI_ID from SMS_CIAllCategories where CategoryInstance_UniqueID='$($UpdateClassificationsTable[$UpdateClassification])') OR ")
}
else {
$SoftwareUpdatesQuery = -join @($SoftwareUpdatesQuery, "CI_ID in (select CI_ID from SMS_CIAllCategories where CategoryInstance_UniqueID='$($UpdateClassificationsTable[$UpdateClassification])')")
}
}
$SoftwareUpdatesQuery = -join @($SoftwareUpdatesQuery, " )")
# Create Software Update Group
$SoftwareUpdates = Get-WmiObject -Namespace "root\SMS\site_$($SiteCode)" -Query $SoftwareUpdatesQuery
if ($SoftwareUpdates -ne $null) {
if (($SoftwareUpdates | Measure-Object).Count -eq 1 ) {
$UpdateList = New-Object -TypeName System.Collections.ArrayList
$UpdateList.Add($SoftwareUpdates.CI_ID) | Out-Null
New-SoftwareUpdateGroupList -SoftwareUpdateGroupName $Name -UpdatesList $UpdateList
}
else {
New-SoftwareUpdateGroupList -SoftwareUpdateGroupName $Name -UpdatesList $SoftwareUpdates.CI_ID
}
}
else {
Write-Warning -Message "Specified search for Software Updates between '$($StartYear)' and '$($EndYear)' did not return any Software Updates"
}
}
You can’t perform that action at this time.