Pete Hinchley: Create an Application in SCCM using PowerShell with a File-System Detection Rule

Although you can create an application in SCCM using the native Configuration Manager cmdlets (e.g. New-CMApplication and Add-CMDeploymentType), you cannot create a script-based deployment that uses a file system (or registry) detection rule. Hence the reason for the following PowerShell script.

The script will create a new application in SCCM 2012 (or later) with the following details: Publisher of Acme, Name of Foobar and Version of 1.0. The content source is \\lab.hinchley.net\software\Acme\Foobar 1.0, the installation command is setup.exe /q, and the file system detection rule looks for a file named foobar.exe, under C:\Windows\System32, with a file version of 1.0.0.

Assuming the script is named CreateApplication.ps1, it should should be executed on the primary site server (by a suitably privileged user) as follows:

powershell -file CreateApplication.ps1

Remember to modify the variables at the top of the script to values suitable for your environment.

# load required 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"
Add-Type -Path "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\DcmObjectModel.dll"
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\AdminUI.AppManFoundation.dll"

# name of vendor.
$publisher = "Acme"

# name of application.
$name = "Foobar"

# version of application.
$release = "1.0"

# installation command.
$install = "setup.exe /q"

# path to source.
$source  = "\\lab.hinchley.net\software\Acme\Foobar 1.0"

# path to file when installed. used by detection method.
$path = "C:\Windows\System32"

# name of installed file. used by detection method.
$file = "foobar.exe"

# version of installed file. used by detection method.
$version = "1.0.0"

# connect to server. 
$connection = New-Object Microsoft.ConfigurationManagement.ManagementProvider.WqlQueryEngine.WqlConnectionManager
[void]$connection.Connect("localhost")

# initialise management scope.
$factory = New-Object Microsoft.ConfigurationManagement.AdminConsole.AppManFoundation.ApplicationFactory
$wrapper = [Microsoft.ConfigurationManagement.AdminConsole.AppManFoundation.AppManWrapper]::Create($connection, $factory)

# create the application.
$app = New-Object Microsoft.ConfigurationManagement.ApplicationManagement.Application

# set the application properties.
$app.Title = $name
$app.Publisher = $publisher
$app.SoftwareVersion = $release

# prepare the localised display info.
$info = New-Object Microsoft.ConfigurationManagement.ApplicationManagement.AppDisplayInfo

# set the localised application name.
$info.Title = $name
$info.Language = "en-AU"

# save the display properties.
$app.DisplayInfo.Add($info)

# create a script-based installer.
$installer = New-Object Microsoft.ConfigurationManagement.ApplicationManagement.ScriptInstaller
$installer.InstallCommandLine = $install

# reference the content source.
$content = [Microsoft.ConfigurationManagement.ApplicationManagement.ContentImporter]::CreateContentFromFolder($source)
$installer.Contents.Add($content)

$reference  =  New-Object Microsoft.ConfigurationManagement.ApplicationManagement.ContentRef
$reference.Id  = $content.Id
$installer.InstallContent =  $reference

# use an enhanced detection method.
$installer.DetectionMethod = [Microsoft.ConfigurationManagement.ApplicationManagement.DetectionMethod]::Enhanced
$detector = New-Object Microsoft.ConfigurationManagement.ApplicationManagement.EnhancedDetectionMethod

# use a file detector.
$type = [Microsoft.ConfigurationManagement.DesiredConfigurationManagement.ConfigurationItemPartType]::File

# prepare the detection settings.
$setting = New-Object Microsoft.ConfigurationManagement.DesiredConfigurationManagement.FileOrFolder($type , $null)

# configure the detection settings.
$setting.FileOrFolderName = $file
$setting.Path = $path
$setting.Is64Bit = 1
$setting.SettingDataType = [Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.DataType]::Version

# save the detection settings.
$detector.Settings.Add($setting)

# configure the setting reference.
$reference = New-Object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.SettingReference($app.Scope, $app.Name, $app.Version, $setting.LogicalName, $setting.SettingDataType, $setting.SourceType, [bool]0)
$reference.MethodType = [Microsoft.ConfigurationManagement.DesiredConfigurationManagement.ConfigurationItemSettingMethodType]::Value
$reference.PropertyPath = "Version"

# create the version comparison value.
$value = New-Object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.ConstantValue($version, [Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.DataType]::Version)

# configure the comparison operands.
$operands = New-Object Microsoft.ConfigurationManagement.DesiredConfigurationManagement.CustomCollection``1[[Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.ExpressionBase]]
$operands.Add($reference)
$operands.Add($value)

# build the comparison expression.
$expression = New-Object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.Expression([Microsoft.ConfigurationManagement.DesiredConfigurationManagement.ExpressionOperators.ExpressionOperator]::IsEquals, $operands)

# save the detection rule.
$rule = New-Object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.Rule("IsInstalledRule", [Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.NoncomplianceSeverity]::None, $null, $expression)

# associate the detection rule with the detection method.
$detector.Rule = $rule 

# associate the detector with the installer.
$installer.EnhancedDetectionMethod = $detector

# create the deployment type.
$deployment = New-Object Microsoft.ConfigurationManagement.ApplicationManagement.DeploymentType($installer, [Microsoft.ConfigurationManagement.ApplicationManagement.ScriptInstaller]::TechnologyId, [Microsoft.ConfigurationManagement.ApplicationManagement.NativeHostingTechnology]::TechnologyId)

# name the deployment type after the application.
$deployment.Title = $name

# associate the deployment type with the application.
$app.DeploymentTypes.Add($deployment)

# save the application.
$wrapper.InnerAppManObject = $app
$factory.PrepareResultObject($wrapper)
$wrapper.InnerResultObject.Put()