As I already mentioned using PowerShell with SCCM 2012 is still not optimal. Automating application creation and maintenance is still a lot of manual work. Today I want to show you an solution I created to add an Global condition to a deployment rule.
The advantage you can create is that an application installs only when the hardware is valid according to your policies. Until now there is no function you can call which create a global condition rule. Below you can find my solution
<# .SYNOPSIS Creates a Global Condition rule of type [Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.Rule]. This rule can be added as a requirement for an deployment type .DESCRIPTION This function will Create a rule for an global condition .PARAMETER GlobalCondition Name of the global condition you wanted to use .PARAMETER Operator Operator used to validate the rule. Accepted values are Equals,NotEquals,GreaterThan,LessThan,Between,GreaterEquals,LessEquals,BeginsWith,NotBeginsWith,EndsWith,NotEndsWith,Contains,NotContains,AllOf,OneOf,NoneOf,SetEquals .PARAMETER Value Value on which the rule should check. Use MB when data value is needed .PARAMETER SiteServerName Name of the SCCM Site server to check Global Conditions .EXAMPLE Create-SCCMGlobalConditionsRule "TotalPhysicalMemory" "GreaterEquals" 524288000 . Creates a rule where Total Phyiscal memory is greater than or equals to 500 MB .EXAMPLE Create-SCCMGlobalConditionsRule "CPU" "GreaterThan" 10000 . Creates a rule where the cpu speed is greater than 1 GHZ #> Function Create-SCCMGlobalConditionsRule($GlobalCondition,$Operator, $Value,$siteServerName){ if($GlobalCondition.ModelName -eq $null){ $GlobalCondition = Get-SCCMGlobalCondition $GlobalCondition $siteServerName } if($GlobalCondition -eq $null){ Write-Error "Global condition not found" } $gcTmp = $GlobalCondition.ModelName.Split("/") $gcScope = $gcTmp[0] $gcLogicalName = $gcTmp[1] $gcDataType = $GlobalCondition.DataType $gcExpressionDataType = [Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.DataType]::GetDataTypeFromTypeName($gcDataType) $arg = @($gcScope, $gcLogicalName, $gcExpressionDataType, "$($gcLogicalName)_Setting_LogicalName", ([Microsoft.ConfigurationManagement.DesiredConfigurationManagement.ConfigurationItemSettingSourceType]::CIM) ) $reqSetting = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.GlobalSettingReference -ArgumentList $arg $arg = @( $value, $gcExpressionDataType ) $reqValue = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.ConstantValue -ArgumentList $arg $operands = new-object "Microsoft.ConfigurationManagement.DesiredConfigurationManagement.CustomCollection``1[[Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.ExpressionBase]]" $operands.Add($reqSetting) | Out-Null $operands.Add($reqValue) | Out-Null $Expoperator = Invoke-Expression [Microsoft.ConfigurationManagement.DesiredConfigurationManagement.ExpressionOperators.ExpressionOperator]::$operator if( $GlobalCondition.DataType -eq "OperatingSystem"){ $operands = new-object "Microsoft.ConfigurationManagement.DesiredConfigurationManagement.CustomCollection``1[[Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.RuleExpression]]" foreach( $os in $value){ $operands.Add($os) } $arg = @( $Expoperator , $operands ) $expression = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.OperatingSystemExpression -ArgumentList $arg }else{ $arg = @( $Expoperator , $operands ) $expression = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.Expression -ArgumentList $arg } $anno = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.Annotation $annodisplay = "$GlobalCondition.LocalizedDisplayName $operator $value" $arg = @( "DisplayName", $annodisplay, $null ) $anno.DisplayName = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.LocalizableString -ArgumentList $arg $arg = @( ("Rule_" + [Guid]::NewGuid().ToString()), [Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.NoncomplianceSeverity]::None, $anno, $expression ) $rule = new-object "Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.Rule" -ArgumentList $arg return $rule }
The only thing you now have to do is call this function and save it
$rule = Create-SCCMGlobalConditionsRule "CPu" "GreaterThan" 1000 . $app.DeploymentTypes[0].Requirements.Add($rule) $rule = Create-SCCMGlobalConditionsRule "Global/OperatingSystem" "OneOF" @("Windows/All_x64_Windows_XP_Professional") . $app.DeploymentTypes[0].Requirements.Add($rule) Save-SCCMApplication $app
Hi Robert, it’s difficult to find good information to the CM 2012 SDK, so thanks for your interesting blog. since a couple of days I’m looking for a sample to create a Global Condition like “Create-SCCMGlobalCondition”. Do you have some source or hints for C# or PS? Kind Regards Jens
Hi Jens,
I have a draft version of something that looks like creating a global condition. This one only creates a global condition that looks at a file. Don’t know if your looking for that? Or do you want to create another global condition…. Let me know and I will post the code when I made it better to read.
Regards Rob
Dear all
Thank you for the ps script that i try to use to create a desired configuration rule.
But, i have a problem with Device_oslanguage or OsLanguage global condition because i can’t create a rule, in fact the rule is created but reject by sccm when i check deployment type \ rules
coul’d you check your script to see what it is eventualy wrong
i try to resolve my problem without success
many thanks
ps : i try parameter 1033, English, en-US…> failed
Hi Rob
thanks for your answer. We have different ‘operating companies’ in our structure and we can differ them using AD / OU structure. I could made an deployment type rule for an OUValue, but I would prefer a global condition like “Organizational unit (OU) One of {DC=mydomain,DC=com(Include sub OU)}”. And I would prefer to define the AuthoringScopeID and logical name like “COMPANY-GLOBAL/MY-LOGICAL-NAME”.
Thanks for your help!
Hi Rob,
I am very new when it comes to powershell! Would appreciate if you could maybe help me with the following:
I want to add a requirement rule to an existing deployment type. The rule is a Global condition that already exists. I’m not interested in creating a rule but add an existing one to an existing application/deployment type. I have looked at your blog but do not really understand what I need to do to achieve what I want. Would be very happy if you could help me with an example that does what I want and also specify where I need to change for it to work with my rule and application.
The Requirement rule looks like this:
Category: Custom
Condition: “Choose my Global condition”
Rule type: Existential
X – The selected global condition must exist on client devices
Awesome script. Thank you for posting.
Thanks for this! Very helpful, but do you know how to get it working for the “User Primary Device” condition?
Download my new script
link
and use the following command”line
Create-SCCMGlobalConditionsRule . “PrimaryDevice” “IsEquals” “True”
I’m not sure what I changed last time to get it working but now I am seeing an error on the save function –
Exception calling “Put” with “0” argument(s): “Generic failure ”
I had to make some changes to get it working remotely but I did have it working in the last version although it doesn’t appear like you made any drastic changes….
Not that I know. Which command did you use and can you check the smsprov.log on the SCCM server you connect to.
Here are the logs I see…the error seems obvious just not sure why it’s occurring –
CObjectLock::UserHasLock: ********** User MYDOMAIN\####### has acquired lock for object SMS_Application.CI_ID=16794749 with LockID: F8EF1C38-D560-49E2-8266-BD975036D9A2 ********** $$
SQL MESSAGE: sp_SetupCI – Caught error: XML Validation: Invalid simple type value: ‘Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.Glo’. Location: /*:AppMgmtDigest[1]/*:DeploymentType[1]/*:Requirements[1]/*:Rule[1]/*:GlobalExpression[1]/@*:LogicalName $$
error 12: SQL Error Message (null)~ $$
ERROR CCISource::InsertObject returned 12~ $$
~*~*~e:\qfe\nts\sms\siteserver\sdk_provider\smsprov\sspconfigurationitem.cpp(2140) : The digest is not valid~*~*~ $$
~*~*~The digest is not valid ~*~*~ $$
CObjectLock::ReleaseLock: ********** User MYDOMAIN\####### has released lock for object SMS_Application.CI_ID=16794749 with LockID: F8EF1C38-D560-49E2-8266-BD975036D9A2 ********** $$
Auditing: User MYDOMAIN\####### called an audited method of an instance of class SMS_Application.~ $$
CExtUserContext::LeaveThread : Releasing IWbemContextPtr=57680336~ $$
Found it –
$expression = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.GlobalExpression -ArgumentList $arg
should be
$expression = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.Expression -ArgumentList $arg
Hi
Thank you for the ps script that i try to use to create a desired configuration rule about oslanguage,but it failed (no rule created available on console)
coul’d you tell me what is the parameter to pass to the script
for example “en-us” ? “0409” for result” Anglais (Etats Unis)”
i used it for device_operatingsystem or diskspace and it’s ok
many thanks
Hi, David.
Thank you for your awesome blog.
Using this post I was able to create a new custom Global Condition with simple settings.
Now I need to create Global Condition with expression like when you go to “Create Global Condition” and in “Condition Type” you select “Expression”. After that you can add different clauses.
I found a way to create such type of Global Condition, but I could not understand the way to add Clauses there. I’m trying to do that for a long time, so if you could help me, I’d very much appreciate it.
Thanks!