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 mnscug.org.
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.
ConfigMgr-DeploymentType-Restrictive-Requirement
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 {
<# .SYNOPSIS Add an additional OS deployment to an existing OS requirement for a Deployment Type .DESCRIPTION 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 https://github.com/fredbainbridge/Add-FBApplicationDTDeploymentType 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. .EXAMPLE Add-FBApplicationDTRequirement -appName "Microsoft Office 2016 x86" -siteCode "lab" -siteserver "cm01.cm.lab" -Requirement "All Windows 10 (64-bit)" .EXAMPLE $appNames | Add-FBApplicationDTRequirement -siteCode "lab" -siteserver "cm01.cm.lab" -Requirement "All Windows 10 (64-bit)" .PARAMETER appName 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. .PARAMETER siteCode 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. #>
[CmdletBinding()]
param (
    [Parameter(
        Position=0,
        Mandatory=$true, 
        ValueFromPipeline=$true,
        ValueFromPipelineByPropertyName=$true)       
    ]
    $appName,
    $siteCode = "LAB",
    $siteServer = "cm01.cm.lab"   
)
 
dynamicparam {
    $attributes = new-object System.Management.Automation.ParameterAttribute
    $attributes.ParameterSetName = "__AllParameterSets"
    $attributes.Mandatory = $true
    $attributeCollection = new-object -Type System.Collections.ObjectModel.Collection[System.Attribute]
    $attributeCollection.Add($attributes)
    $values =   Get-Content .\NameValidateSet.txt | ForEach-Object {
                    "$($PSItem.Split(",")[0])" 
                } 
    $ValidateSet = new-object System.Management.Automation.ValidateSetAttribute($values)
    #write-host $ValidateSet.ValidValues
    $attributeCollection.Add($ValidateSet)
 
    $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.Expression.Operands.Add("$operand")
                $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)
                Break
            }
        }
    }
}
$UpdatedXML = [Microsoft.ConfigurationManagement.ApplicationManagement.Serialization.SccmSerializer]::SerializeToString($XML, $True) 
$appdt.SDMPackageXML = $UpdatedXML 
$appdt.put()
$t = Set-CMApplication -InputObject $appDT -PassThru
 
}
 
end
{
set-location c:
}
}

2 thoughts on “ConfigMgr – Add OS Requirements to an application deployment type”

  1. Hello this does not work for me. i get the error that ‘APPNAME’ is not recognised…see below.

    PS C:Add-FBApplicationDTDeploymentType-master> .Add-CMApplicationDTRequirement.ps1 | -appName “adobe dc” -sitecode P03 -siteserver PR3.LAB1.COM -Requirement “All Windows 10 (64-bit)”
    -appName : The term ‘-appName’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was
    included, verify that the path is correct and try again.
    At line:1 char:40
    + .Add-CMApplicationDTRequirement.ps1 | -appName “adobe dc” -sitecode P03 -sitese …
    + ~~~~~~~~
    + CategoryInfo : ObjectNotFound: (-appName:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    1. Your syntax is slightly off. Try this (remove the “|” after the script name) –
      .Add-CMApplicationDTRequirement.ps1 -appName “adobe dc” -sitecode P03 -siteserver PR3.LAB1.COM -Requirement “All Windows 10 (64-bit)”

Leave a Reply

Your email address will not be published. Required fields are marked *