Creating SCCM Global Conditions by Script

I’ve written a fair bit about automating SCCM application creation by script.  Most of this has originated from the need to use Enhanced Detection Methods for determining when Applications are installed as I know from many years of Application Packaging that unless an official “package” produces a standard file or registry based flag when it’s installed, it becomes impossible to tightly manage a software environment. 

One of the advantages of being forced to study how SCCM Applications are created with Dot Net is that working code can be easily translated between Powershell and C#.  This has meant that I could create compiled utilities for automating SCCM Application creation, purely based of “official” package summaries created by Application Packaging Teams. 

The answer for simply creating SCCM Global Conditions is by using PowerShell cmdlets.  The example below creates a Global Condition that can be used for identifying when Dot Net 4.0 is installed on a machine... useful when a Deployment Type runs a Dot Net compiled executable.

[[powershell]]
New-CMGlobalCondition -DeviceType Windows -FileOrFolderName "NativeImages_v4.0.30319_64" -Name "DotNet 4.5" -Path "C:\Windows\assembly" -Description "Test for DotNet Framework 4" –IsFolder
[[/powershell]]

Doing the same thing without using PowerShell cmdlets takes a bit more code.

[[powershell]]
#WQL Connection to Server
Add-Type -Path "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\AdminUI.WqlQueryEngine.dll"
Add-Type -Path "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\DcmObjectModel.dll"

 
[string]$sSCCMServerName           = "SCCMServer"
[string]$sSCCMUsername              = "SCCMUsername"
[string]$sSCCMPassword              = "SCCMPassword"

function WQLConnect($Server, $User, $Password) {
 
  $namedValues              = New-Object Microsoft.ConfigurationManagement.ManagementProvider.SmsNamedValuesDictionary
  if ($namedValues -ne $null) { write-host " namedValues object Created"} else {write-host " namedValues object Creation failed"; exit}
 
  $connection               = New-Object Microsoft.ConfigurationManagement.ManagementProvider.WqlQueryEngine.WqlConnectionManager
  if ($connection  -ne $null) { write-host " connection  object Created"} else {write-host " connection  object Creation failed"; exit}
 
 
  # Connect with credentials if not running on the server itself
  if ($env:computername.ToUpper() -eq $Server.ToUpper()){
     write-host  "Local WQL Connection Made"
     [void]$connection.Connect($Server)
  }
  else
  {
     write-host  "Remote WQL Connection Made: " + $sSCCMServerName
     [void]$connection.Connect($Server, $User, $Password)
 
  }
  return $connection
 
}


$oServerConnection  = WQLConnect $sSCCMServerName $sSCCMUsername $sSCCMPassword

$dcmConnectionObj = new-object Microsoft.ConfigurationManagement.AdminConsole.DesiredConfigurationManagement.ConsoleDcmConnection -ArgumentList $oServerConnection, $null

#The object was implemented with explicit interfaces
$dcmConnection = Get-Interface $dcmConnectionObj ([Microsoft.ConfigurationManagement.DesiredConfigurationManagement.IDcmStoreConnection])               
 
[Microsoft.ConfigurationManagement.DesiredConfigurationManagement.GlobalSettingsConfigurationItem]$GlobalCI = [Microsoft.ConfigurationManagement.DesiredConfigurationManagement.GlobalSettingsConfigurationItem]::CreateNew($dcmConnectionObj, [Microsoft.ConfigurationManagement.DesiredConfigurationManagement.ConfigurationItemType]::GlobalSettings)
 
$GlobalCI.Description = "Test for DotNet Framework 4"
$GlobalCI.Name = "DotNet 4.5"
$GlobalCI.Type = [Microsoft.ConfigurationManagement.DesiredConfigurationManagement.ConfigurationItemType]::GlobalSettings

#SCCM 2012 category ID string values
#GlobalCondition:7437C28A-EA1F-46e5-A722-2C016B436D45 = “Device”
#GlobalCondition:C7AB132C-3B96-4882-9B34-8F7656566273 = “User”
#GlobalCondition:08347928-D747-4b2e-B99C-94876C0D3D74 = “Custom”

$GlobalCI.CategoryIDs = [string[]] "GlobalCondition:08347928-D747-4b2e-B99C-94876C0D3D74"



# File / Folder Detection - (Determined by Part property)
#

$folder = new-object Microsoft.ConfigurationManagement.DesiredConfigurationManagement.FileOrFolder([Microsoft.ConfigurationManagement.DesiredConfigurationManagement.ConfigurationItemPartType]::Folder, $null)
$folder.FileOrFolderName = "NativeImages_v4.0.30319_64" 
$folder.Path = "C:\Windows\assembly"
$folder.Type = [Microsoft.ConfigurationManagement.DesiredConfigurationManagement.ConfigurationItemPartType]::Folder


$GlobalCI.Parts.Add($folder)

#Store the new Configurtion Item
$newItem = $dcmConnection.StoreNewItem([Microsoft.ConfigurationManagement.DesiredConfigurationManagement.ConfigurationItem]$GlobalCI)
 


[[/powershell]]

The important element that isn’t necessarily clear is that Global Conditions differentiate between two main categories of “Settings Type”.   These are associated with two different properties on the Global Condition object.  The example uses File & Folder detection – which is a “Configuration Item Part” whereas other forms of Condition will use “Simple Settings” depending on what type of detection is being used.

Configuration Item Part 

The Global Conditions that utilise the Configuration Item Part are: 

  • Assembly
  • FileOrFolder
  • MSISettingInstance
  • RegistryKey

 These are added to the Configurtion Information object  with “$GlobalCI.Parts.Add()”

Simple Settings

The Global Conditions that utilise Simple Settings are: 

  • ActiveDirectoryQuerySetting
  • CIMSetting
  • IisMetabaseSetting
  • MacDetectionSetting
  • RegistrySetting
  • ScriptSetting
  • SqlQuerySetting
  • UriSetting
  • WqlQuerySetting
  • XPathQuerySetting

 These are added to the Configurtion Information object  with “$GlobalCI.Settings.ChildSimpleSettings.Add($simplesetting)” instead of uing "Parts.Add"

The same example above could use a Simple Setting object as shown below.

[[powershell]]
$SimpleSetting = new-object Microsoft.ConfigurationManagement.DesiredConfigurationManagement.WqlQuerySetting $GlobalCI

#Set the datatype for WQL 
$SimpleSetting.SettingDataType = [Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.DataType]::String

$SimpleSetting.WqlClass     = "SMS_R_System";
$SimpleSetting.WqlNamespace = "ROOT\ccm";
$SimpleSetting.WhereClause  = "";
$SimpleSetting.WqlProperty  = "ClientType";
$SimpleSetting.Description  = "Example WQL CI"
$SimpleSetting.Name         = "WQL ClientType"


$GlobalCI.Settings.ChildSimpleSettings.Add($SimpleSetting)

[[/powershell]]

Related posts that may be of interest are:

Creating SCCM Applications with Powershell, Constructing SCCM Rules with Powershell,  Scripting SCCM Application Dependencies