Example Scripting - SCCM 2012 Application Dependencies

A number of previous posts have provided examples of how to script against SCCM 2012 Applications.

The script below is an example of how to attach a Deployment Type dependency rule to a scripted application.  If you havent done so, take the time to have a look at my recent blog into SCCM rules to get a better idea of what is happening.

Dependency Example

This example script will create an application called "RhubarbApp1" .  When the application is created, a dependency link will be made to an application titled "VisualC2010_10.00_86a".  You'll notice the creation of an "Intent Expression" to create a rule between the two applications.  

This is an example script, to use a similar script in production, have a look at using PowerShell credential objects instead of readable passwords. :)

[[powershell]]
cls
#####################################################
# Add Required Type Libraries
 
Add-Type -Path "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\Microsoft.ConfigurationManagement.ApplicationManagement.dll"
Add-Type -Path "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\Microsoft.ConfigurationManagement.ApplicationManagement.MsiInstaller.dll"
Add-Type -Path "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\Microsoft.ConfigurationManagement.ManagementProvider.dll"
Add-Type -Path "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\Microsoft.ConfigurationManagement.ApplicationManagement.Extender.dll"
#used for creating rules
Add-Type -Path "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\DcmObjectModel.dll"
#WQL Connection to Server
Add-Type -Path "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\AdminUI.WqlQueryEngine.dll"
#Application Wrapper and Factory
Add-Type -Path "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\AdminUI.AppManFoundation.dll"
 
 
 
#####################################################
# Core Application Details
 
# Core Application Details
 
[string]$sPackageDirectory         ="\\Mediavault\software\Applications\7Zip_09.20_64a"
[string]$sApplicationName          = "RhubarbApp1"
[string]$sApplicationDestription   = "Example Application"
[string]$sApplicationVersion       = "02.00"
[string]$sApplicationPublisher     = "Vendor A"
[string]$ApplicationOwner          = ""
 
[string]$sSCCMServerName           = "SCCMServer"
[string]$SMSSiteCode               = "MEL"
[string]$sSCCMUsername             = "fred"
[string]$sSCCMPassword             = "MyPassword001"
 
$arrDependentApps = @( "VisualC2010_10.00_86a" )
 
 
 
#####################################################
# Functions
 
# WQLConnect
# Purpose: To create a WQL query connection to an SCCM Server
#          This will utilise credentials if script isn't being run on the server itself
#
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
 
}
 
# Store
# Purpose: To commit the completed application to SCCM
#
function store ($Application){
 
                # Set the application into the provider object.
                $oAppManWrapper.InnerAppManObject = $Application
 
                # "Initializing the SMS_Application object with the model."
                $oApplicationFactory.PrepareResultObject($oAppManWrapper);
 
                # Save to the database.
                $oAppManWrapper.InnerResultObject.Put();
}
 
 
#####################################################
# Main
 
#create connection to SCCMServer (not used until the end of the script)
$oServerConnection                       = WQLConnect $sSCCMServerName $sSCCMUsername $sSCCMPassword
$oApplicationFactory                     = New-Object Microsoft.ConfigurationManagement.AdminConsole.AppManFoundation.ApplicationFactory
$oAppManWrapper                           = [Microsoft.ConfigurationManagement.AdminConsole.AppManFoundation.AppManWrapper]::Create( $oServerConnection , $oApplicationFactory)
 
 
write-host  "Creating Application Object"
$oApplication                        = New-Object Microsoft.ConfigurationManagement.ApplicationManagement.Application
   if ($oApplication -ne $null) { write-host " oApplication object Created"} else {write-host " oApplication object Creation failed"; exit}
  
$oApplication.Title                       = $sApplicationName
$oApplication.SoftwareVersion             = $sApplicationVersion
$oApplication.Publisher                   = $sApplicationPublisher
$oApplication.DisplayInfo.DefaultLanguage = "en-US"
 
write-host  "Creating Application Display Info"
 
$oApplicationDisplayInfo = New-Object Microsoft.ConfigurationManagement.ApplicationManagement.AppDisplayInfo
  if ($oApplicationDisplayInfo -ne $null) { write-host " oApplicationDisplayInfo object Created"} else {write-host " oApplicationDisplayInfoo object Creation failed"; exit}
 
 
$oApplicationDisplayInfo.Title            = $sApplicationName
$oApplicationDisplayInfo.Description      = $sApplicationDestription
$oApplicationDisplayInfo.Language         = "en-US"
$oApplication.DisplayInfo.DefaultLanguage = "en-US"
$oApplication.DisplayInfo.Add($oApplicationDisplayInfo)
 
 
$oAppinstaller = New-Object Microsoft.ConfigurationManagement.ApplicationManagement.ScriptInstaller
  if ($oAppinstaller -ne $null) { write-host " oAppinstaller object Created"} else {write-host " oAppinstaller object Creation failed"; exit}
 
#Note that this example hardcodes install and remove syntax by using
#a launcher for all applications
 
$oAppinstaller.InstallCommandLine          = '"Launcher.exe"'
$oAppinstaller.UninstallCommandLine        = '"Launcher.exe" /Remove'
 
#####################################################
# Upload File Content to Server
 
write-host  "Upload Content"
 
$oContent                                   = [Microsoft.ConfigurationManagement.ApplicationManagement.ContentImporter]::CreateContentFromFolder($sPackageDirectory)
$oContent.OnSlowNetwork                     = "Download"
$oAppinstaller.Contents.Add($oContent)
 
 
#####################################################
# Main Creating Enhanced File Detection Method (file based)
# This uses a standard Package signature file under c:\windows\logs
# to determine if the package is installed
 
write-host  "Enabling Enhanced File Detection"
$oAppinstaller.DetectionMethod = [Microsoft.ConfigurationManagement.ApplicationManagement.DetectionMethod]::Enhanced
$oEnhancedDetection = New-Object Microsoft.ConfigurationManagement.ApplicationManagement.EnhancedDetectionMethod
  if ($oEnhancedDetection -ne $null) { write-host " oEnhancedDetection object Created"} else {write-host " oEnhancedDetection object Creation failed"; exit}
 
$oDetectionType              = [Microsoft.ConfigurationManagement.DesiredConfigurationManagement.ConfigurationItemPartType]::File
$oFileSetting                 = New-Object Microsoft.ConfigurationManagement.DesiredConfigurationManagement.FileOrFolder( $oDetectionType , $null)
  if ($oFileSetting -ne $null) { write-host " oFileSetting object Created"} else {write-host " oFileSetting object Creation failed"; exit}
 
$oFileSetting.FileOrFolderName = $sApplicationName + ".sig"
$oFileSetting.Path             = "%Windir%\Logs"
$oFileSetting.Is64Bit          = 1
$oFileSetting.SettingDataType  = [Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.DataType]::Int64
 
$oEnhancedDetection.Settings.Add($oFileSetting)
 
 
write-host  "Settings Reference"
$oSettingRef                  = New-Object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.SettingReference(
$oApplication.Scope,
$oApplication.Name,
$oApplication.Version,
$oFileSetting.LogicalName,
$oFileSetting.SettingDataType,
$oFileSetting.SourceType,
[bool]0 )
# setting bool 0 as false
if ($oSettingRef -ne $null) { write-host " oSettingRef object Created"} else {write-host " oSettingRef object Creation failed"; exit}
 
 
$oSettingRef.MethodType    = [Microsoft.ConfigurationManagement.DesiredConfigurationManagement.ConfigurationItemSettingMethodType]::Value
$oConstValue               = New-Object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.ConstantValue( 0, 
[Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.DataType]::Int64)
   if ($oConstValue -ne $null) { write-host " oConstValue object Created"} else {write-host " oConstValue object Creation failed"; exit}
 
$oFileCheckOperands = new-object Microsoft.ConfigurationManagement.DesiredConfigurationManagement.CustomCollection``1[[Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.ExpressionBase]]
$oFileCheckOperands.Add($oSettingRef)
$oFileCheckOperands.Add($oConstValue)
 
$FileCheckExpression = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.Expression(
[Microsoft.ConfigurationManagement.DesiredConfigurationManagement.ExpressionOperators.ExpressionOperator]::NotEquals, $oFileCheckOperands)
 
$oRule              = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.Rule("IsInstalledRule", 
[Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.NoncomplianceSeverity]::None, $null, $FileCheckExpression)
   if ($oRule  -ne $null) { write-host " rule object Created"} else {write-host " rule object Creation failed"; exit}
 
 
$oEnhancedDetection.Rule = $oRule 
$oAppinstaller.EnhancedDetectionMethod = $oEnhancedDetection
 
#####################################################
# Add Deployment Type to Application
 
 
write-host  "Adding Deployment Type"
$oApplicationDeploymentType = new-object Microsoft.ConfigurationManagement.ApplicationManagement.DeploymentType($oAppinstaller, 
[Microsoft.ConfigurationManagement.ApplicationManagement.ScriptInstaller]::TechnologyId, 
[Microsoft.ConfigurationManagement.ApplicationManagement.NativeHostingTechnology]::TechnologyId)
 
if ($oApplicationDeploymentType -ne $null) { write-host " NewApplicationDeploymentType object Created"} else {write-host " NewApplicationDeploymentType object Creation failed"; exit}
 
 
$oApplicationDeploymentType.Title = $oApplication.Title
 
  
#####################################################
 
write-host "Limiting Collections to 64bit workstations"
 
$oOperands = new-object "Microsoft.ConfigurationManagement.DesiredConfigurationManagement.CustomCollection``1[[Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.RuleExpression]]"

$oOperands.Add("Windows/All_x64_Windows_XP_Professional")
$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")
 
$oOSExpression           = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.OperatingSystemExpression -ArgumentList `
([Microsoft.ConfigurationManagement.DesiredConfigurationManagement.ExpressionOperators.ExpressionOperator]::OneOf), $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 x86 Windows XP (64bit)}", $null
 
$oDTRule = new-object "Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.Rule" -ArgumentList `
            ("Rule_" + [Guid]::NewGuid().ToString()), 
            ([Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.NoncomplianceSeverity]::None), 
             $oAnnotation, 
             $oOSExpression
 
write-host "Adding Deployment Type rule to Application"     
$oApplicationDeploymentType.Requirements.Add($oDTRule)

# Add Deployment Type to Application
$oApplication.DeploymentTypes.Add($oApplicationDeploymentType)
 

#####################################################

write-host "Adding Dependencies (if they exist)"

#This routine  reads the open XML file for the names of Dependency packages

foreach ($Dependency in $arrDependentApps)
{if ($Dependency -ne $null) {
      Write-host "Adding Dependency: " + $Dependency

    $sPath  = [string]::Format("\\{0}\ROOT\sms\site_{1}", $sSCCMServerName, $SMSSiteCode)
    $oScope = new-object System.Management.ManagementScope -ArgumentList $sPath
    if ($oScope -ne $null) { write-host " oScope object Created"} else {write-host " oScope object Creation failed"; exit}
    
    $oQuery                      = new-object System.Management.ObjectQuery -ArgumentList ([string]::Format("select * from sms_application where LocalizedDisplayName='{0}' and IsEnabled=1", $Dependency.Trim()))
    $oManagementObjectSearcher   = new-object System.Management.ManagementObjectSearcher -ArgumentList $oScope,$oQuery
    $ResultsCollection           = $oManagementObjectSearcher.Get()    
    $ResultsCollectionEnumerator = $ResultsCollection.GetEnumerator()
    
    #$ResultsCollection

    #foreach ($ResultsCollectionEnumerator.MoveNext())
    foreach ($Result in $ResultsCollection)
    {

        $getResult        = $Result.Get()        
        
        [xml]$sdmPackageXml  = New-Object system.Xml.XmlDocument
             $sdmPackageXml.LoadXml($Result.Properties["SDMPackageXML"].Value.ToString())
     

        if($oFoundDependency -ne $null )
        {
            Write-host " Application Retrieved:"
            $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 "sAuthScope = $sAuthScope"  
#              Write-host "sLogicalName = $sLogicalName"
#              Write-host "sVersion = $sAppVersion"
#              Write-host "sDTAuthScope = $sDTAuthScope"
#              Write-host "sDTLogicalName = $sDTLogicalName"
#              Write-host "sDTAppVersion = $sDTAppVersion"
              

            $oIntentExpression = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.DeploymentTypeIntentExpression -ArgumentList `
                               $sAuthScope, 
                               $sLogicalName, 
                               $sAppVersion, 
                               $sDTAuthScope, 
                               $sDTLogicalName, 
                               $sDTVersion, 
                               ([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)
            
            if ($oAnnotation -ne $null) { write-host " oAnnotation object Created"} else {write-host " oAnnotation object Creation failed"; exit}
                
            $oDeploymentTypeRule = new-object "Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.DeploymentTypeRule" -ArgumentList  ([Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.NoncomplianceSeverity]::Critical, $oAnnotation, $oExpression)
            if ($oDeploymentTypeRule -ne $null) { write-host " oDeploymentTypeRule object Created"} else {write-host " oDeploymentTypeRule object Creation failed"; exit}

            $oApplicationDeploymentType.Dependencies.Add($oDeploymentTypeRule)
        }
    }
    }
    }

############################################
# Finish
  
# Verify the Application structure
write-host "Verifying Application Object"  
$oApplication.Validate
 
#Add Application to SCCM
write-host "Loading SCCM Application"  
Store $oApplication
[[/powershell]]

Related posts that may be of interest are:

Creating SCCM Applications with PowershellConstructing SCCM Rules with Powershell,  Creating SCCM Global Conditions