ConfigMgr – Add OS Requirements to an application deployment type

This was updated again 6/1/2017. Changes were needed in order to avoid corruption. Mainly, a new GUID needed to be generated and used in order to ensure the changes were recognized. Hat tip to Jeff Scripter for figuring this out. Thank you.
This was updated 6/21/2016. The script was over hauled to handle windows 10, multiple deployment types and more.
The script and supported files can be found on github here. This is inspired by this post at
If you are anything like me, perhaps you created a lot of applications in ConfigMgr and decided to configure your deployment types such that there were restrictive in nature as to what Operating Systems they would be able to be deployed to.
This works great! Until you are ready to migrate to new version of the Operating System and now you have to modify every single deployment type.
PowerShell to the rescue – This adds the Windows 8.1 OS to the requirements. See here for how to get all the OS requirements by querying the CM database.
The script and supported files can be found on github here. The NameValidatSet.txt must be in the working directory of the script. This is used to create a dynamic Requirement parameter.
function Add-FBApplicationDTRequirement {
Add an additional OS deployment to an existing OS requirement for a Deployment Type
This is especially useful if you have a lot of applications that have existing OS requirements attached to deployment
types and you want to add another.  i.e. Windows 10 just came.  There must already be an OS requirement for the deployment 
type for this to work.
The NameValidateSet.txt must exist in the working directory of the script.
It can be found here
This needs to be run on a system that has the ConfigMgr console installed and it assumes it is installed here - 
  'C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1'
  Modify the begin statement to change this.
This will attempt to add the OS requirement only if it finds an existing OS requirement.
This will attempt to add the OS requirement to each deployment type it finds.
Add-FBApplicationDTRequirement -appName "Microsoft Office 2016 x86" -siteCode "lab" -siteserver "" -Requirement "All Windows 10 (64-bit)"
$appNames | Add-FBApplicationDTRequirement -siteCode "lab" -siteserver "" -Requirement "All Windows 10 (64-bit)"
This is the name of the configmgr application that has the deployment types that you want to add the OS requirement to. This accepts input from pipeline.
This the ConfigMgr site code you are working with. Defaults to LAB
.PARAMETER siteServer
This the site server you are going to working with.  WMI calls are made to this server.  It is most likely your primary site server.
param (
    $siteCode = "LAB",
    $siteServer = ""   

dynamicparam {
    $attributes = new-object System.Management.Automation.ParameterAttribute
    $attributes.ParameterSetName = "__AllParameterSets"
    $attributes.Mandatory = $true
    $attributeCollection = new-object -Type System.Collections.ObjectModel.Collection[System.Attribute]
    $values =   Get-Content .\NameValidateSet.txt | ForEach-Object {
    $ValidateSet = new-object System.Management.Automation.ValidateSetAttribute($values)
    #write-host $ValidateSet.ValidValues

    $dynParam1 = new-object -Type System.Management.Automation.RuntimeDefinedParameter("Requirement", [string], $attributeCollection)
    $paramDictionary = new-object -Type System.Management.Automation.RuntimeDefinedParameterDictionary
    $paramDictionary.Add("Requirement", $dynParam1)
    return $paramDictionary 
begin {
import-module "$($ENV:SMS_ADMIN_UI_PATH)\..\ConfigurationManager.psd1"  -force #make this work for you
if ((get-psdrive $sitecode -erroraction SilentlyContinue | measure).Count -ne 1) {
    new-psdrive -Name $SiteCode -PSProvider "AdminUI.PS.Provider\CMSite" -Root $SiteServer

#create the hash
$NamedPairs = @{};
Get-Content .\NameValidateSet.txt | ForEach-Object {
    $name = $PSItem.Split(",")[0]
    $operand = $PSItem.Split(",")[1]
    $NamedPairs.Add($name, $operand)

set-location $sitecode`:


process {
$Appdt = Get-CMApplication -Name $appName 
$xml = [Microsoft.ConfigurationManagement.ApplicationManagement.Serialization.SccmSerializer]::DeserializeFromString($appdt.SDMPackageXML,$True)

$numDTS = $xml.DeploymentTypes.count
$dts = $xml.DeploymentTypes

$operand = $NamedPairs[$dynParam1.Value].trim()
$namedRequirement = $dynParam1.Value
Write-Verbose "Operand $operand"
Write-Verbose "Requirement $namedRequirement"
foreach ($dt in $dts)
    foreach($requirement in $dt.Requirements)
        if($requirement.Expression.gettype().name -eq 'OperatingSystemExpression') 
            If ($requirement.Name -Notlike "*$namedRequirement*" )
                write-verbose "Found an OS Requirement, appending value to it"
                $requirement.Name = [regex]::replace($requirement.Name, '(?<=Operating system One of {)(.*)(?=})', "`$1, $namedRequirement")
                $null = $dt.Requirements.Remove($requirement)
                $requirement.RuleId = "Rule_$([guid]::NewGuid())"
                $null = $dt.Requirements.Add($requirement)
$UpdatedXML = [Microsoft.ConfigurationManagement.ApplicationManagement.Serialization.SccmSerializer]::SerializeToString($XML, $True) 
$appdt.SDMPackageXML = $UpdatedXML 
$t = Set-CMApplication -InputObject $appDT -PassThru


set-location c: