SCCM 2012 R2 – Exporting an application with PowerShell

Recently i have been doing some work for a client that likes to segregate their environment for test and production. While this is great for many reasons, one of the downsides is having to export an application and then import it into the next environment.

In this post i will be showing a PowerShell script that I developed to export applications from SCCM 2012 R2 to a predetermined folder. I will also do my best to explain each step of the script. As usual this script should work on SCCM 2012 and SCCM 2012 SP1 but I have only tested it on SCCM 2012 R2


##Script written by Liam Matthews 2015

##Variable list
$SCCMModule = “C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1”
$SCCMSiteCode = “001”
$SCCMDrive = $SCCMSiteCode + “:”
$SCCMServer = “SCCM2012.liammatthewsit.com”
$ExportPathDirect = “E:\SCCM Export\”

##Progress bar
Write-Progress -Activity “Application Export” -Status “Starting Script” -PercentComplete 10

##Import SCCM PowerShell module
Import-Module $SCCMModule

##Connect to SCCM site
CD $SCCMDrive

##Pause to show previous display message
Start-Sleep 5

##Progress bar
Write-Progress -Activity “Application Export” -Status “Searching for applications” -PercentComplete 30

##Get applicaion list via WMI
$Applications = Get-WMIObject -ComputerName $SCCMServer -Namespace Root\SMS\Site_$SCCMSiteCode -Class “SMS_Application” | Select -unique LocalizedDisplayName | sort LocalizedDisplayName

##Application Import Selection Form
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

$form1 = New-Object System.Windows.Forms.Form
$form1.Text = “Application Import”
$form1.Size = New-Object System.Drawing.Size(425,380)
$form1.StartPosition = “CenterScreen”

$OKButton1 = New-Object System.Windows.Forms.Button
$OKButton1.Location = New-Object System.Drawing.Point(300,325)
$OKButton1.Size = New-Object System.Drawing.Size(75,23)
$OKButton1.Text = “OK”
$OKButton1.DialogResult = [System.Windows.Forms.DialogResult]::OK
$OKButton1.Anchor = [System.Windows.Forms.AnchorStyles]::Bottom -bor [System.Windows.Forms.AnchorStyles]::Right
$form1.AcceptButton = $OKButton1
$form1.Controls.Add($OKButton1)

$CancelButton1 = New-Object System.Windows.Forms.Button
$CancelButton1.Location = New-Object System.Drawing.Point(225,325)
$CancelButton1.Size = New-Object System.Drawing.Size(75,23)
$CancelButton1.Text = “Cancel”
$CancelButton1.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$CancelButton1.Anchor = [System.Windows.Forms.AnchorStyles]::Bottom -bor [System.Windows.Forms.AnchorStyles]::Right
$form1.CancelButton = $CancelButton1
$form1.Controls.Add($CancelButton1)

$label1 = New-Object System.Windows.Forms.Label
$label1.Location = New-Object System.Drawing.Point(10,5)
$label1.Size = New-Object System.Drawing.Size(280,20)
$label1.Text = “Select an application to import”
$form1.Controls.Add($label1)

$listBox1 = New-Object System.Windows.Forms.Listbox
$listBox1.Location = New-Object System.Drawing.Size(10,30)
$listBox1.Width = 400
$listBox1.Height = 296
$listBox1.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Left -bor [System.Windows.Forms.AnchorStyles]::Bottom -bor [System.Windows.Forms.AnchorStyles]::Right

##Add items to form
foreach($Application in $Applications)
{
[void] $ListBox1.Items.Add($Application.LocalizedDisplayName)
}

$form1.Controls.Add($listBox1)
$form1.Topmost = $True
$result1 = $form1.ShowDialog()
if ($result1 -eq [System.Windows.Forms.DialogResult]::OK)
{
$SelectedApplication = $listBox1.SelectedItems
$SelectedApplication = $SelectedApplication[0]
}
else
{
exit
}

##Progress bar
Write-Progress -Activity “Application Export” -Status “Exporting $SelectedApplication” -PercentComplete 60

##Export selected application
$ExportPath = $ExportPathDirect + $SelectedApplication + “.zip”
Export-CMApplication -IgnoreRelated -Path $ExportPath -Name $SelectedApplication

##Progress bar
Write-Progress -Activity “Application Export” -Status “Finalizing” -PercentComplete 90

##Rename exported folders to deployment type name
$DeploymentTypes = Get-CMDeploymentType -ApplicationName $SelectedApplication
foreach ($DeploymentType in $DeploymentTypes)
{
$OldContentName = $ExportPathDirect + $SelectedApplication + “_files\” + $DeploymentType.ContentId
$NewContentName = $DeploymentType.LocalizedDisplayName
$NewContentName = $NewContentName.Replace(“|”,””)
$NewContentName = $NewContentName.Replace(“\”,””)
$NewContentName = $NewContentName.Replace(“/”,””)
$NewContentName = $NewContentName.Replace(“?”,””)
$NewContentName = $NewContentName.Replace(“*”,””)
$NewContentName = $NewContentName.Replace(“<“,””)
$NewContentName = $NewContentName.Replace(“>”,””)
Rename-Item -NewName $NewContentName -Path $OldContentName
}

##Progress bar
Write-Progress -Activity “Application Export” -Status “Export of $SelectedApplication Completed” -PercentComplete 100

##Pause to show previous display message
Start-Sleep 5


OK, so there is the script in its entirety, lets go ahead and start breaking this down

I will be skipping over anything to do with the progress bar and anything that has Start-Sleep as these are both for the user to see


##Variable list

$SCCMModule = “C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1”
$SCCMSiteCode = “001”
$SCCMDrive = $SCCMSiteCode + “:”
$SCCMServer = “SCCM2012.liammatthewsit.com”
$ExportPathDirect = “E:\SCCM Export\”

In this section we are defining the variables that we will be using in the script. Not all variables can be created at this stage because they may rely on information that we do not currently have, anything that does not will be listed here so that it is easy to find


##Import SCCM PowerShell module
Import-Module $SCCMModule

##Connect to SCCM site
CD $SCCMDrive

These commands import the SCCM module and then connect to the appropriate drive (Which would be your site code)


##Get applicaion list via WMI
$Applications = Get-WMIObject -ComputerName $SCCMServer -Namespace Root\SMS\Site_$SCCMSiteCode -Class “SMS_Application” | Select -unique LocalizedDisplayName | sort LocalizedDisplayName

This will connect to WMI on the SCCM server and fetch a list of all applications that currently exist, note that it filters out duplicated via “Select -unique”. Within WMI there will be several versions of an application listed, this is because each revision will be displayed as though it is a different application

Some people might be asking “Why are you not using the module command to get a list of applications?” I have used WMI because it is a faster query than “Get-CMApplication”. This may not be a big issue if you are using this in a lab or you only have a few dozen applications, but when the number of applications exceeds 500 then you might as well take your lunch break while it runs

If you are keen you can change this line to the following (you will also be able to remove the $SCCMServer variable

$Applications = Get-CMApplication | Select LocalizedDisplayName | sort LocalizedDisplayName


##Application Import Selection Form
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

$form1 = New-Object System.Windows.Forms.Form
$form1.Text = “Application Import”
$form1.Size = New-Object System.Drawing.Size(425,380)
$form1.StartPosition = “CenterScreen”

$OKButton1 = New-Object System.Windows.Forms.Button
$OKButton1.Location = New-Object System.Drawing.Point(300,325)
$OKButton1.Size = New-Object System.Drawing.Size(75,23)
$OKButton1.Text = “OK”
$OKButton1.DialogResult = [System.Windows.Forms.DialogResult]::OK
$OKButton1.Anchor = [System.Windows.Forms.AnchorStyles]::Bottom -bor [System.Windows.Forms.AnchorStyles]::Right
$form1.AcceptButton = $OKButton1
$form1.Controls.Add($OKButton1)

$CancelButton1 = New-Object System.Windows.Forms.Button
$CancelButton1.Location = New-Object System.Drawing.Point(225,325)
$CancelButton1.Size = New-Object System.Drawing.Size(75,23)
$CancelButton1.Text = “Cancel”
$CancelButton1.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$CancelButton1.Anchor = [System.Windows.Forms.AnchorStyles]::Bottom -bor [System.Windows.Forms.AnchorStyles]::Right
$form1.CancelButton = $CancelButton1
$form1.Controls.Add($CancelButton1)

$label1 = New-Object System.Windows.Forms.Label
$label1.Location = New-Object System.Drawing.Point(10,5)
$label1.Size = New-Object System.Drawing.Size(280,20)
$label1.Text = “Select an application to import”
$form1.Controls.Add($label1)

$listBox1 = New-Object System.Windows.Forms.Listbox
$listBox1.Location = New-Object System.Drawing.Size(10,30)
$listBox1.Width = 400
$listBox1.Height = 296
$listBox1.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Left -bor [System.Windows.Forms.AnchorStyles]::Bottom -bor [System.Windows.Forms.AnchorStyles]::Right

This is a long one, I am not going to go through each line one at a time. this section creates a list box. The bulk of this code was taken from the Microsoft Technet article on list boxes, however is was modified to make it expandable when dragged


##Add items to form
foreach($Application in $Applications)
{
[void] $ListBox1.Items.Add($Application.LocalizedDisplayName)
}

$form1.Controls.Add($listBox1)
$form1.Topmost = $True
$result1 = $form1.ShowDialog()
if ($result1 -eq [System.Windows.Forms.DialogResult]::OK)
{
$SelectedApplication = $listBox1.SelectedItems
$SelectedApplication = $SelectedApplication[0]
}
else
{
exit
}

Here we are feting the data from the $Applications variable that we specified earlier and turning each entry into an item in the list box. The bottom half of this code also specifies the action that is taken when the OK button is pressed. In this case it is to assign the selected item to a variable that we can use later


##Export selected application
$ExportPath = $ExportPathDirect + $SelectedApplication + “.zip”
Export-CMApplication -IgnoreRelated -Path $ExportPath -Name $SelectedApplication

This is where all the magic happens. Here we are using all the variables that we have created to export the application to the folder the we specified at the top of the script


##Rename exported folders to deployment type name
$DeploymentTypes = Get-CMDeploymentType -ApplicationName $SelectedApplication
foreach ($DeploymentType in $DeploymentTypes)
{
$OldContentName = $ExportPathDirect + $SelectedApplication + “_files\” + $DeploymentType.ContentId
$NewContentName = $DeploymentType.LocalizedDisplayName
$NewContentName = $NewContentName.Replace(“|”,””)
$NewContentName = $NewContentName.Replace(“\”,””)
$NewContentName = $NewContentName.Replace(“/”,””)
$NewContentName = $NewContentName.Replace(“?”,””)
$NewContentName = $NewContentName.Replace(“*”,””)
$NewContentName = $NewContentName.Replace(“<“,””)
$NewContentName = $NewContentName.Replace(“>”,””)
Rename-Item -NewName $NewContentName -Path $OldContentName
}

This section is entirely optional, however, when the application is exported is puts the source files in a folder which is named with the Deployment Type GUID. When we are using a script to import this we will run into several problems because it will have no idea which folder belongs to which Deployment Type

This part of the script will rename each folder to the Deployment Type name so that it is easier to reference this later. When using this script though you will need to make sure that every Deployment Type name in your environment is unique, otherwise you are going to run into duplicate folder problems


Hopefully this script will prove useful and you have a good understanding of how it functions so that you can modify to suite your environment. If you have any questions or don’t understand something in the script then please comment

Stay tuned to the import script that will be following shortly

2 thoughts on “SCCM 2012 R2 – Exporting an application with PowerShell

  1. Hi Liam;

    I have one question why when i replace the site code with my site code and server name I receive an error on site code.unexpected token “DE1”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s