Constructing SCCM Rules with PowerShell

System Center heavily uses rules for definining how software elements relate with each other.  They aren't extensively documented but must be understood by anyone trying to script SCCM applications.   At the highest level, a rule can be seen to comprise of an Expression and an Annotation that are combined with an overall severity level for noncompliance.  The same structure I used throughout System Center so the severity level of noncompliance changes on the type of rule being used. 

The best way to see how SCCM rules are constructed is to export a working application and then extracting the created XML files from the exported zip file.

Non-Compliance SEVERITY

There are five potential severity ratings, “None”, “Informational”, “Warning”, “Critical” and “Critical with Event” although SCCM rules seem to be “Critical” or “None”, depending on the type of rule being created.  To be certain of the type of severity a rule uses, the best approach is to manually create a rule for an application and verifying the value of the Severity attribute within the element.

Annotations

The annotation component of a rule is the text string that gets displayed through the Configuration Manager console.

Annotations are constructed of a Requirement Type, Operator and Value.

Annotation examples are as single strings with list values enclosed in {braces}

"Operating system One of {All Windows 7 (64-bit), All Windows 8 (64-bit), All Windows 8.1 (64-bit)}"
"Total physical memory Greater than or equal to 1000 MB"
"Existential of NativeImages_v2.0.50727_64 Not equal to 0"
"Number of processors Equals 1"
"Operating system language One of {English (Australia), English, English (New Zealand), English (United Kingdom), English (United States)}"
"Organizational unit (OU) One of {CN=Computers,DC=Domain,DC=com(Include sub OU)}"/>
"Windows Store inactive Not equal to 1"/>
"Existential of NativeImages_v4.0.30319_64 Not equal to 0"/>

 

Expressions

Constructing System Center rules is like peeling back layers of an onion.  The outer layer comprises of an Annotation, Severity and Expression but the expression itself can’t be understood without looking at the object in terms of its constructed elements.

Expresssions are comprised of two “Operands” and an “Operator (such as as “equals”, “one of” , “and”, “greater than”, “not equal” etc).  Generally Operands will reference to a particular “setting” and a particular Value.  Therefore, an expression could be seen as defining the relationship between a particular setting and a particular value. 

Considering the some of the common annotations makes it easier to understand how an expression is broken into its constituent Operands and operator.

Eg.

Annotation Text="Number of processors Equals 1"
The setting being referenced is “number of processors”, the operator for the rule is “equals”, and the “constant value” is “1”.

 

Annotation Text="Total physical memory Greater than or equal to 1000 MB"
The setting being referenced is “Total physical memory, the operator against the setting is “greater than”,” and the “constant value” is “1000 MB”.

 

The next layer of the onion to peel back is to see how the Operands are constructed of different components.  A graphic representation of a SCCM expression is shown below

Note how cleanly the elements of an expression match up to the XML structure of an exported Application from SCCM.

There are some slight variations on expressions but the general concept is the same. 

Settings Reference operands are provided by DcmObjectModel.dll and the “Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions” namespace.  As objects they tend to be either “GlobalSettingReference” or “SettingReference”

The other variation is in regard to the type of list used for Operands.  Types of collection are linked to specific types objects.

Type

Collection Type

Expression

ExpressionBase

DeploymentTypeExpression

DeploymentTypeIntentExpression

OperatingSystemExpression

RuleExpression

Microsoft have tried to define a flexible framework for creating rules that can be modified with different types of objects as technology demands.  It’s difficult to follow some of the framework from a high level but by copying working routines and comparing them to exported SCCM Application XML files it becomes possible to properly recreate rules by script.

I’ve pasted copies of a selection of code I’ve used to create SCCM Application elements below

The rules below are examples of using PowerShell to construct rules on SCCM Deployment Types.  The examples can be used with an example PowerShell script (http://www.laurierhodes.info/?q=node/61) to create an SCCM 2012 Application in entity.  Alternatively, this variation on the script (http://www.laurierhodes.info/sites/default/files/ApplicationScript.ps1) can be used to set dependency relationships between applications.

 

PowerShell / SCCM Rule Example – Requiring Minimum Disk Space for a deployment

This example is a rule requiring minimum disk space on a machine for an install to occur.  When the Settings Reference is declared it' using a GLOBAL scope which means it's builtin to the system and available to any "scope".

# Create the rule components.  First a Setting Reference
#
 
$oSettingReference = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.GlobalSettingReference  -ArgumentList ( "GLOBAL",
"FreeDiskSpace",
[Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.DataType]::Int64,
"FreeSpace",
[Microsoft.ConfigurationManagement.DesiredConfigurationManagement.ConfigurationItemSettingSourceType]::CIM)
 
# The contstant value is set
#Note the size in bytes
 
$oConstantValue = New-Object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.ConstantValue( (5000 * 1024 * 1024).ToString(),
[Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.DataType]::Int64)
 
# The operand is created from the SettingReference and the Constant Value
 
$operands = new-object "Microsoft.ConfigurationManagement.DesiredConfigurationManagement.CustomCollection``1[[Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.ExpressionBase]]"
 
$operands.Add($oSettingReference)
$operands.Add($oConstantValue)
 
#The Expression represents the operands and operator    
 
$oExpression= new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.Expression(
[Microsoft.ConfigurationManagement.DesiredConfigurationManagement.ExpressionOperators.ExpressionOperator]::GreaterThan, $operands)
 
# Create the Rule and add it to the Deployment Type
 
$oAnnotationSpace             = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.Annotation     
$oAnnotationSpace.DisplayName = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.LocalizableString -ArgumentList (
"DisplayName", "Free Disk Space of any local drive Greater than 5000 MB", $null)
 
$RuleFreeSpace  = new-object "Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.Rule"  -ArgumentList (("FreeSpaceRule_" + [Guid]::NewGuid().ToString()), 
([Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.NoncomplianceSeverity]::Critical), $oAnnotationSpace , $fullExp)
 
$oApplicationDeploymentType.Requirements.Add($RuleFreeSpace)

PowerShell / SCCM Rule Example – Limiting Deployments to certain Operating Systems

The Operands and an Operator are brought together to form an expression.  The expression, annotation and severity rating are then combined to form a rule.  In this case, the particular type of expression is an “Operating System Expression”.  This rule limits the deployment of an appliction to Windows 7, 8 and 8.1 clients.

$oOperands = new-object "Microsoft.ConfigurationManagement.DesiredConfigurationManagement.CustomCollection``1[[Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.RuleExpression]]"
 
$oOperands.Add("Windows/All_x64_Windows_7_Client")
$oOperands.Add("Windows/All_x64_Windows_8_Client")
$oOperands.Add("Windows/All_x64_Windows_8.1_Client")
 
$oOperator     = [Microsoft.ConfigurationManagement.DesiredConfigurationManagement.ExpressionOperators.ExpressionOperator]::OneOf
 
$oOSExpression = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.OperatingSystemExpression `
-ArgumentList $oOperator, $oOperands   
 
$oAnnotation             = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.Annotation     
 
$oAnnotation.DisplayName = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.LocalizableString `
-ArgumentList "DisplayName", "Operating system One of {All Windows 7 (64-bit), All Windows 8 (64-bit), All Windows 8.1 (64-bit)}", $null
 
$oNoncomplianceSeverity = [Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.NoncomplianceSeverity]::None
 
$oDTRule = new-object "Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.Rule" -ArgumentList (
            ("Rule_" + [Guid]::NewGuid().ToString()),
            $oNoncomplianceSeverity,
             $oAnnotation,
             $oOSExpression)
 
$oApplicationDeploymentType.Requirements.Add($oDTRule)

 

PowerShell / SCCM Rule Example – Creating a Dependency to another application

Linking other applications as dependencies requires searching for the existing applications to discover the specifics of that application.  This rule example begins after a specific application object has been found ($oFoundDependency). 

$sAuthScope           = $oFoundDependency.Scope
$sLogicalName         = $oFoundDependency.Name 
$sAppVersion          = $oFoundDependency.Version
$sDTAuthScope         = $oFoundDependency.DeploymentTypes[0].Scope
$sDTLogicalName       = $oFoundDependency.DeploymentTypes[0].Name
$sDTAppVersion        = $oFoundDependency.DeploymentTypes[0].Version
 
Write-host " Name   : $appLogicalName"
Write-host " Version: $dtAppVersion" 
 
$oIntentExpression = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.DeploymentTypeIntentExpression -ArgumentList `
$sAuthScope,
$sLogicalName,
$sAppVersion,
$sDTAuthScope,
$sDTLogicalName,
$sDTAppVersion,
([Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.DeploymentTypeDesiredState]::Required ),
$true
 
$oOperands = new-object "Microsoft.ConfigurationManagement.DesiredConfigurationManagement.CustomCollection``1[[Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.DeploymentTypeIntentExpression]]"
 
$oOperands.Add($oIntentExpression)
 
$oExpression = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.DeploymentTypeExpression -ArgumentList ([Microsoft.ConfigurationManagement.DesiredConfigurationManagement.ExpressionOperators.ExpressionOperator]::Or),$oOperands
 
 
$oAnnotation =  new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.Annotation
 
$oAnnotation.Description = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.LocalizableString -ArgumentList "Description", $sLogicalName, $null
 
$oAnnotation.DisplayName = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.LocalizableString -ArgumentList "DisplayName", $sLogicalName, $null
 
 
$oDeploymentTypeRule = new-object "Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.DeploymentTypeRule" -ArgumentList  ([Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.NoncomplianceSeverity]::Critical, $oAnnotation, $oExpression)
 
$oDeploymentType.Dependencies.Add($oDeploymentTypeRule)

 

PowerShell / SCCM Rule Example – Using File based Detection

With this rule example, Enhanced Detection is set to look for a file (or registry key) to indicate a successful install.  A full example may be found: http://www.laurierhodes.info/?q=node/61

$DataType_String = [Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.ScalarDataType]::GetDataTypeFromDotNetTypeName("String")
 
$oDetectionSetting = new-object Microsoft.ConfigurationManagement.DesiredConfigurationManagement.FileOrFolder -ArgumentList ([Microsoft.ConfigurationManagement.DesiredConfigurationManagement.ConfigurationItemPartType]::File), $null
$oDetectionSetting.FileOrFolderName = "PackageName_01.sig"   
$oDetectionSetting.Path = "C:\Windows\Logs"
$logicalName = $oDetectionSetting.LogicalName 
 
# Create the rule components.  First a Setting Reference
#
 
$oSettingReference = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.SettingReference `
       -ArgumentList ($sScopeID,
        "SettingRef_" + [Guid]::NewGuid().ToString(),
        0,
        $logicalName,
        $DataType_String,
        ([Microsoft.ConfigurationManagement.DesiredConfigurationManagement.ConfigurationItemSettingSourceType]::File) ,
        $false)
 
$oSettingReference.MethodType = [Microsoft.ConfigurationManagement.DesiredConfigurationManagement.ConfigurationItemSettingMethodType]::Count
 
# The contstant value is set
 
$oConstantValue = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.ConstantValue -ArgumentList "0",$DataType_String
 
# The operand is created from the SettingReference and the Constant Value
 
$operands       = new-object "Microsoft.ConfigurationManagement.DesiredConfigurationManagement.CustomCollection``1[Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.ExpressionBase]"
 
$operands.Add($oSettingReference)   
$operands.Add($oConstantValue)
 
 
#The Expression represents the operands and operator   
 
$oExpression = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.Expression -ArgumentList `
 ([Microsoft.ConfigurationManagement.DesiredConfigurationManagement.ExpressionOperators.ExpressionOperator]::NotEquals),
 $operands
 
# The rule is an expression, severity rating and Annotation (in this case $null)
 
$oRule              = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.Rule(("Rule_" + [Guid]::NewGuid().ToString()),
 
[Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.NoncomplianceSeverity]::None, $null, $oExpression)
 
$oEnhancedDetection.Rule = $oRule
$oAppinstaller.EnhancedDetectionMethod = $oEnhancedDetection

 

PowerShell / SCCM Rule Example – Deployment Type based on the Existence of a file

This example references a pre-existing Global Setting that detects DotNet 4 (http://www.laurierhodes.info/?q=node/89).  This rule is applied to a Deployment Type if it is only invoked with Dot Net 4 is present on a machine.  A similar rule exists on a second deployment type if Dot Net 3.5 is present. 

# Global Setting Existential rule
 
$DotNetSettingRef = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.GlobalSettingReference  -ArgumentList ( "ScopeId_4481981D-9195-4F90-95EA-79A9C3CF81D8", 
"GlobalSettings_06dce054-cbd7-4566-a584-46fbb7f39637", 
[Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.DataType]::Int64, 
"File_97867e95-11da-4369-8c24-0bb490d173e6", 
[Microsoft.ConfigurationManagement.DesiredConfigurationManagement.ConfigurationItemSettingSourceType]::Folder)
 
$DotNetSettingRef.MethodType = "Count" 
 
#convert to bytes
$constant = New-Object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.ConstantValue(0, 
[Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.DataType]::Int64)
 
# Outer expression that combines the previous expressions
 
$DotNetOperands = new-object "Microsoft.ConfigurationManagement.DesiredConfigurationManagement.CustomCollection``1[[Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.ExpressionBase]]"
 
$DotNetOperands.Add($DotNetSettingRef)
$DotNetOperands.Add($constant)
 
$DotNetExpression = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.Expression(
[Microsoft.ConfigurationManagement.DesiredConfigurationManagement.ExpressionOperators.ExpressionOperator]::NotEquals, $DotNetOperands)
 
# Construct the rule and add it to the Deplyment Type
 
$oAnnotationDotNet             = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.Annotation      
$oAnnotationDotNet.DisplayName = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.LocalizableString -ArgumentList (
"DisplayName", "Existential of NativeImages_v4.0.30319_64 Not equal to 0", $null)
 
$RuleDotNet  = new-object "Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.Rule"  -ArgumentList (("FreeSpaceRule_" + [Guid]::NewGuid().ToString()),  
([Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.NoncomplianceSeverity]::None), $oAnnotationDotNet , $DotNetExpression)
 
$oApplicationDeploymentType.Requirements.Add($RuleDotNet)

Related posts that may be of interest are:

Creating SCCM Applications with PowershellScripting SCCM Application DependenciesCreating SCCM Global Conditions