MSEndpointMgr

How to Add a Product to an ADR in ConfigMgr 2012 R2 with PowerShell

With ConfigMgr 2012 SP1 we received a bunch of new cool cmdlets for PowerShell, and as well for the R2 release, that we could use. This post will concentrate on how you can add a Product as search criteria to an Automatic Deployment Rule in ConfigMgr 2012 R2. One of the many cmdlets that was introduced in the SP1 version, was the Set-CMSoftwareUpdateAutoDeploymentRule. With this cmdlet we’re able to do almost everything with an ADR. But I’ve run into problems when I’ve tried to add a Product under the Software Updates tab of an ADR. Instead I started to explore how the actual WMI object looked like, and decided to create my own script that would take care of this.

Locate the WSUS Product GUID

Let’s say that we want to add Windows 7 to the search criteria for an ADR. First off we need to find the corresponding WSUS Product GUID for Windows 7. This can be done in several ways, and the easiest would be to run the following cmdlet on the Primary Site server (assuming that’s where WSUS is installed):

Get-WsusProduct

This cmdlet will output all the synchronized products in WSUS. Since we want to know the GUID for Windows 7, we can narrow our search a bit by running the following command:

Get-WsusProduct -TitleIncludes "Windows 7"

100_1
The other method we could use is to load the Microsoft.UpdateServices.Administration assembly, and query for an object where the Title is like Windows 7 . Here’s the code to do that:

[Reflection.Assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")
$WSUSServer = $env:COMPUTERNAME
$WSUSPort = "8530"
$WSUSSecure = $false
$WSUSConnection = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($WSUSServer,$WSUSSecure,$WSUSPort)
$WSUSProducts = $WSUSConnection.GetUpdateCategories()
$WSUSProducts | Where-Object {$_.Title -like "Windows 7"} | Select-Object -ExpandProperty Id

Now that we know what the Product GUID for Windows 7 is, we can continue.

Looking at the Automatic Deployment Rule

Before we continue with the script that will add the Windows 7 Product GUID to the ADR, lets take a look at how the ADR looks under the Software Updates tab. Below is a picture where I’ve configured my Critical and Security Patches – Windows Clients rule:
100_2
As we can see, the only two products that are added right now is Windows 8 and Windows 8.1. After we’ve executed our script, Windows 7 should show up here as well.

Adding the Windows 7 Product GUID

Since an ADR object consists of a lot of XML data, we first needs to get the UpdateRuleXML property. Once we have that, the OuterXML property holds the XML data with information about the search criteria shown on the Software Updates tab in the ADR. We then amend it and then save it back to the ADR object. This part is explained below. The full script is available below the explanation.
First we start with defining some necessary variables for connecting to the SMS Provider and what ADR we should look for:

# Define Site variables
$SiteServer = "CAS01.contoso.com"
$SiteCode = "CAS"
# ADR name
$ADRName = "Critical and Security Patches - Windows Clients"

We then create a few more variables, where one of them holds the Windows 7 Product GUID that we got our hands on earlier:

# Windows 7 Product GUID located from WSUS wrapped in single quotations
$WSUSGUID = "bfe5b177-a086-47a0-b102-097e4fa1f807"
$ProductGUID = "'" + "Product:" + "$($WSUSGUID)" + "'"

Now it’s time to connect to the SMS Provider and get the ADR object from WMI. Here we’re interested in the direct WMI object, so we therefor store the __PATH property of the object in a variable called $ADR. Additionally we specify that this is a WMI object with the [wmi]:

# Get the ADR as a WMI object
[wmi]$ADR = (Get-WmiObject -Namespace "root\SMS\site_$($SiteCode)" -Class SMS_AutoDeployment -Filter "Name like '%$($ADRName)%'").__PATH

Once the ADR object has been stored into a variable, we can go ahead and create a new XML variable and load the UpdateRuleXML:

# Create a XML object and load the UpdateRuleXML from the ADR object
$UpdateRuleXML = New-Object -TypeName XML
$UpdateRuleXML.LoadXML($ADR.UpdateRuleXML)

With the UpdateRuleXML loaded, we create a new string element and specifies the InnerText property to be the $ProductGUID variable constructed earlier:

# Create a new string element with the innertext of the Product GUID
$CreateXMLElement = $UpdateRuleXML.CreateElement("string")
$CreateXMLElement.InnerText = "$($ProductGUID)"

Since we now have a new element, it’s time to append it to the UpdateRuleXML:

# Append the child node with the new string element
($UpdateRuleXML.SelectSingleNode("/UpdateXML/UpdateXMLDescriptionItems/UpdateXMLDescriptionItem[@PropertyName='_Product']/MatchRules")).AppendChild($CreateXMLElement) | Out-Null

Now that we have the appended UpdateRuleXML, we save it as a variable:

# Get the OuterXML property
$OuterXML = $UpdateRuleXML.UpdateXML.OuterXml

And at last, we specify the UpdateRuleXML property of the ADR object with the $OuterXML holding the appended XML data and save the ADR object:

# Put the OuterXML on the ADR object
$ADR.UpdateRuleXML = $OuterXML
$ADR.Put()

With all that information about how it works, here’s the complete script that you can use:

# Define Site variables
$SiteServer = "CAS01.contoso.com"
$SiteCode = "CAS"
# ADR name
$ADRName = "Critical and Security Patches - Windows Clients"
# Windows 7 Product GUID located from WSUS wrapped in single quotations
$WSUSGUID = "bfe5b177-a086-47a0-b102-097e4fa1f807"
$ProductGUID = "'" + "Product:" + "$($WSUSGUID)" + "'"
# Get the ADR as a WMI object
[wmi]$ADR = (Get-WmiObject -Namespace "root\SMS\site_$($SiteCode)" -Class SMS_AutoDeployment -Filter "Name like '%$($ADRName)%'").__PATH
# Create a XML object and load the UpdateRuleXML from the ADR object
$UpdateRuleXML = New-Object -TypeName XML
$UpdateRuleXML.LoadXML($ADR.UpdateRuleXML)
# Create a new string element with the innertext of the Product GUID
$CreateXMLElement = $UpdateRuleXML.CreateElement("string")
$CreateXMLElement.InnerText = "$($ProductGUID)"
# Append the child node with the new string element
($UpdateRuleXML.SelectSingleNode("/UpdateXML/UpdateXMLDescriptionItems/UpdateXMLDescriptionItem[@PropertyName='_Product']/MatchRules")).AppendChild($CreateXMLElement) | Out-Null
# Get the OuterXML property
$OuterXML = $UpdateRuleXML.UpdateXML.OuterXml
# Put the OuterXML on the ADR object
$ADR.UpdateRuleXML = $OuterXML
$ADR.Put()

Using the script

Remember to change the script to suite your environment. The SiteServer, SiteCode and ADRName should be amended before you run the script.
1. Save the script above as Set-ADRProduct.ps1 in C:\Scripts.
2. Open an elevated PowerShell console, browse to C:\Scripts and run the following command:

.\Set-ADRProduct.ps1

The output from the script should look something like this, if everything worked out fine:
100_3

Another look at the Automatic Deployment Rule

Now that we’ve  executed the whole script, the Windows 7 product should have been added to the Software Updates tab under search criteria:
100_4
There it is, pretty cool right?
This is not the only thing that you can do with an ADR object. There’s lots of other way that we could change it. But that might be another post for the future.

Nickolaj Andersen

Chief Technical Architect and Enterprise Mobility MVP since 2016. Nickolaj has been in the IT industry for the past 10 years specializing in Enterprise Mobility and Security, Windows devices and deployments including automation. Awarded as PowerShell Hero in 2015 by the community for his script and tools contributions. Creator of ConfigMgr Prerequisites Tool, ConfigMgr OSD FrontEnd, ConfigMgr WebService to name a few. Frequent speaker at conferences such as Microsoft Ignite, NIC Conference and IT/Dev Connections including nordic user groups.

3 comments

  • Hey Nickoaj,
    One can use the SMS_UpdateCategoryInstance to get the Product GUID too. For Example below gives me the one for ‘Windows 7 Client’
    Get-WmiObject -Class SMS_UpdateCategoryInstance -Filter ‘CategoryTypeName=”Product” AND LocalizedCategoryInstanceName=”Windows 7 Client”‘
    Cheers !

Sponsors