More often than we prefer, we are tasked with packaging a new application for a department or user. This typically involves “an investigation” to find the silent switches, how to license it silently without admin intervention, determine the method for updates, and then incorporate it into MECM. For a single application, the process into MECM can involve many clicks, but that’s why there is PowerShell! We will start with a single application and expand to using the same code to do several applications at once.
Single Application
We will start by understanding the basic requirements of the New-CMApplication. All you need is a Name.
New-CMApplication -Name "Test Application"
While this meets the basic requirements to create an application, it won’t do anything for us. Let’s add the other information to make the application more useful.
New-CMApplication -Name "Test Application" -Publisher "Publisher Name" -SoftwareVersion "1.0" -LocalizedName "Test Application" -IconLocationFile "\\SERVER\Share\Sources\icon.png"
Now that we have the basics for the application, we need to add the deployment type to the application with Add-CMScriptDeploymentType or Add-CMMSIDeploymentType. This is the real meat and potatoes of the application where we define the source locations, install commands, and detection methods. For this example, I’ll use the Add-CMScriptDeploymentType.
Add-CMScriptDeploymentType -ApplicationName "Test Application" -DeploymentTypeName "Test Application Silent Install" -ContentLocation "\\SERVER\Share\Sources" -InstallCommand "install.cmd" -ScriptLanguage PowerShell -ScriptFile "\\SERVER\Share\Sources\detectionScript.ps1" -InstallationBehaviorType InstallForSystem -UserInteractionMode Hidden -LogonRequirementType WhereOrNotUserLoggedOn -EstimatedRuntimeMins 10 -MaximumRuntimeMins 30
There are several other options, particularly for detection methods, but for simplicity of this post, we will stick with the script detection method. Now that we’ve created our application and added a deployment type, we still need to distribute the content and deploy the application. To distribute the content, we need to determine if we are distributing to a single distribution point or a group. In most cases, I’d recommend the group, and you can run the following command:
Start-CMContentDistribution -ApplicationName "Test Application" -DistributionPointGroupName "Site Distribution Group"
Lastly, if we want to deploy this to a specific collection, we can do that too.
New-CMApplicationDeployment -CollectionName "Collection Name" -Name "Test Application" -DeployPurpose "Available"
Now, putting that all together and adding in a few variables, we have a nice little script for creating an application.
$ApplicationName = "Test Application"
$PublisherName = "Publisher Name"
$SoftwareVersion = "1.0"
$DeploymentName = "Test Application Silent Install"
$IconFile = "\\SERVER\Share\Sources\icon.png"
$ContentLocation = "\\SERVER\Share\Sources"
$InstallCommand = "install.cmd"
$DetectionFile = "\\SERVER\Share\Sources\detectionScript.ps1"
$DPGroup = "Site Distribution Group"
$CollectionName = "Collection Name"
New-CMApplication -Name $ApplicationName -Publisher $PublisherName -SoftwareVersion $SoftwareVersion -LocalizedName $ApplicationName -IconLocationFile $IconFile
Add-CMScriptDeploymentType -ApplicationName $ApplicationName -DeploymentTypeName $DeploymentName -ContentLocation $ContentLocation -InstallCommand $InstallCommand -ScriptLanguage PowerShell -ScriptFile $DetectionFile -InstallationBehaviorType InstallForSystem -UserInteractionMode Hidden -LogonRequirementType WhereOrNotUserLoggedOn -EstimatedRuntimeMins 10 -MaximumRuntimeMins 30
Start-CMContentDistribution -ApplicationName $ApplicationName -DistributionPointGroupName $DPGroup
New-CMApplicationDeployment -CollectionName $CollectionName -Name $ApplicationName -DeployPurpose "Available"
Applications by CSV
What if we have several applications that we need to create at the same time? Maybe we are deploying updated printer applications, updated BIOS applications, or just have a list of applications that we can put into a CSV. Either way, we can use the same script with a few modifications for scale to allow for the increase in applications. Let’s take a look by first importing the CSV.
$Applications = Import-Csv "$env:USERPROFILE\Desktop\ApplicationList.csv"
This code will import a CSV named “ApplicationList.csv” from the Desktop of the user running the script to a variable. That CSV just needs to have columns populated with the values of all the variables that we were using in the previous script: ApplicationName, PublisherName, SoftwareVersion, DeploymentName, IconFile, ContentLocation, InstallCommand, DetectionFile, DPGroup, and CollectionName. Then, we just need to loop through the CSV objects and create the applications, line by line. A quick way to create an empty CSV file with the desired column headers could be to run the following code:
#Option 1
Add-Content -Path "$env:USERPROFILE\Desktop\ApplicationList.csv" -Value '"ApplicationName","PublisherName","SoftwareVersion","DeploymentName","IconFile","ContentLocation","InstallCommand","DetectionFile","DPGroup","CollectionName"'
#Option 2
$Headers = [pscustomobject]@{ApplicationName=$null;PublisherName=$null;SoftwareVersion=$null;DeploymentName=$null;IconFile=$null;ContentLocation=$null;InstallCommand=$null;DetectionFile=$null;DPGroup=$null;CollectionName=$null}
$Headers | Export-Csv -Path "$env:USERPROFILE\Desktop\ApplicationList.csv" -NoTypeInformation
Then, you can modify your CSV and enter in the expected values for your applications and use the bulk script below to create all of them at once.
$Applications = Import-Csv "$env:USERPROFILE\Desktop\ApplicationList.csv"
$Applications | ForEach-Object {
$ApplicationName = $_.ApplicationName
$PublisherName = $_.PublisherName
$SoftwareVersion = $_.SoftwareVersion
$DeploymentName = $_.DeploymentName
$IconFile = $_.IconFile
$ContentLocation = $_.ContentLocation
$InstallCommand = $_.ContentLocation
$DetectionFile = $_.DetectionFile
$DPGroup = $_.DPGroup
$CollectionName = $_.CollectionName
New-CMApplication -Name $ApplicationName -Publisher $PublisherName -SoftwareVersion $SoftwareVersion -LocalizedName $ApplicationName -IconLocationFile $IconFile
Add-CMScriptDeploymentType -ApplicationName $ApplicationName -DeploymentTypeName $DeploymentName -ContentLocation $ContentLocation -InstallCommand $InstallCommand -ScriptLanguage PowerShell -ScriptFile $DetectionFile -InstallationBehaviorType InstallForSystem -UserInteractionMode Hidden -LogonRequirementType WhereOrNotUserLoggedOn -EstimatedRuntimeMins 10 -MaximumRuntimeMins 30
Start-CMContentDistribution -ApplicationName $ApplicationName -DistributionPointGroupName $DPGroup
New-CMApplicationDeployment -CollectionName $CollectionName -Name $ApplicationName -DeployPurpose "Available"
}
Just like that, you have as many applications created and deployed as you want. These PowerShell cmdlets are extremely flexible, so with a little bit more creativity, you can deploy to multiple collections, use different detection methods, or use different deployment types. Refine your script to a full-on function or use a quick-and-dirty one that you have saved and can copy and paste in when you need to use it. Any way that you can save yourself some time and typos and automate a task, it’s worth the learning effort.
Next time: I’ll write about a Github tool that’s been around for a bit, but really adds to our automation, CMPackager. Like several other 3rd-party packaging tools out there, this one helps to automatically download and package applications for us, but it is flexible for our needs and automation and it’s free! Until next time, keep automating!