When you’re doing a migration and migrate Packages and Deployments that are associated with them, the best practice is to not let the migration wizard enable the Program for each Package after the migration has successfully completed. Instead, it’s a good idea to review the Packages and their configuration before you enable the Programs, as written on TechNet here:

By default, collection-based migration jobs disable advertisements that migrate to the destination hierarchy. This includes any programs that are associated with the advertisement. When you create a collection-based migration job that contains advertisements, you see the Enable programs for deployment in Configuration Manager 2012 after an advertisement is migrated option on the Settings page of the Create Migration Job Wizard. If you select this option, programs that are associated with the advertisements are enabled after they have migrated. As a best practice, do not select this option and instead, enable the programs after they have migrated when you can verify the clients that will receive them.

Once you have verified all of the Programs, it could be quite time consuming to go through all of the Programs for each Package. Instead, we can leverage PowerShell to list all Packages with a disabled Program, and then enable those Programs. In order to do this, I’ve put together a small script that will help you along the way. Save the script below as Get-CMDisabledPrograms.ps1 in e.g. C:\Scripts on your Primary Site server (or CAS if you’re running a hierarchy).

    List all Disabled Programs of Packages in ConfigMgr 2012
    Use this script to list all of the disabled Programs for each Package in ConfigMgr 2012. This script will also give you the option to enable those Programs.
    Site server name with SMS Provider installed
    Specify this switch only if you wish to enable the disable Programs. Don't specify it if you wish to only list the disabled Programs.
    .\Get-CMDisabledPrograms.ps1 -SiteServer CM01 -Verbose
    Lists all disabled Programs and their Package Name association on a Primary Site server called 'CM01':
    Script name: Get-CMDisabledPrograms.ps1
    Author: Nickolaj Andersen
    Contact: @NickolajA
    DateCreated: 2015-03-10
[parameter(Mandatory=$true, HelpMessage="Site server where the SMS Provider is installed")]
    [parameter(Mandatory=$false, HelpMessage="Enable disabled programs")]
Begin {
    # Determine SiteCode from WMI
    try {
        Write-Verbose "Determining SiteCode for Site Server: '$($SiteServer)'"
        $SiteCodeObjects = Get-WmiObject -Namespace "root\SMS" -Class SMS_ProviderLocation -ComputerName $SiteServer -ErrorAction Stop -Verbose:$false
        foreach ($SiteCodeObject in $SiteCodeObjects) {
            if ($SiteCodeObject.ProviderForLocalSite -eq $true) {
                $SiteCode = $SiteCodeObject.SiteCode
                Write-Debug "SiteCode: $($SiteCode)"
    catch [Exception] {
        Throw "Unable to determine SiteCode"
    # Set SiteDrive variable
    $SiteDrive = $SiteCode + ":"
    # Get current location
    $CurrentLocation = $PSScriptRoot
    # Import ConfigMgr PowerShell module
    Import-Module (Join-Path -Path (($env:SMS_ADMIN_UI_PATH).Substring(0,$env:SMS_ADMIN_UI_PATH.Length-5)) -ChildPath "\ConfigurationManager.psd1" -Verbose:$false) -Force -Verbose:$false
    if ((Get-PSDrive $SiteCode -ErrorAction SilentlyContinue | Measure-Object).Count -ne 1) {
        New-PSDrive -Name $SiteCode -PSProvider "AdminUI.PS.Provider\CMSite" -Root $SiteServer -Verbose:$false
Process {
    # Change location to the Site Drive
    Set-Location $SiteDrive -Verbose:$false
    # Get all Programs
    $Programs = Get-WmiObject -Namespace "root\SMS\site_$($SiteCode)" -Class SMS_Program -ComputerName $SiteServer -Verbose:$false
    if ($Programs -ne $null) {
        foreach ($Program in $Programs) {
            if ($Program.ProgramFlags -eq ($Program.ProgramFlags -bor "0x00001000")) {
                $PSObject = [PSCustomObject]@{
                    "PackageName" = $Program.PackageName
                    "ProgramName" = $Program.ProgramName
                if ($PSBoundParameters["Enable"]) {
                    Write-Verbose -Message "Enabling program '$($Program.ProgramName)' for package '$($Program.PackageName)'"
                    try {
                        Get-CMProgram -ProgramName $Program.ProgramName -PackageId $Program.PackageID -Verbose:$false | Enable-CMProgram -Verbose:$false -ErrorAction Stop
                    catch {
                        Write-Warning -Message "Unable to enable program '$($Program.ProgramName)' for package '$($Program.PackageName)'"
                else {
                    Write-Output $PSObject
    else {
        Write-Warning -Message "No Programs found"
End {
    Set-Location -Path $CurrentLocation

Using the script

For this script I’ve chosen to make use of the ConfigMgr 2012 PowerShell cmdlets, or at least one of them, the Enable-CMProgram cmdlet. For this script to work, you’d have to run it on a machine that has the PowerShell module installed (that means it needs to have the ConfigMgr console installed). The script can either show the disabled Programs only, or it can enable them as well if you give a certain parameter called Enable. In order to demonstrate this, I’ve created two test Packages called Test Package 001 and Test Package 002 in my lab environment. For both of these Packages, I’ve created a single Program that I’ve disabled manually.


List disabled Programs

To list all of the disabled Programs, perform the following steps:

1. Once you have downloaded the script above, open an elevated PowerShell console and browse to where you saved the script e.g. C:\Scripts.
2. Run the following command:

.\Get-CMDisabledPrograms.ps1 -SiteServer CAS01 -Verbose


3. The script outputs a custom PowerShell object showing the name of the Program and Package.

Enabled the disabled Programs

Now that we’ve listed those Programs that are disabled, we can go ahead and try to enable them.

1. Open an elevated PowerShell console and run the following command:

.\Get-CMDisabledPrograms.ps1 -SiteServer CAS01 -Enable -Verbose


2. As you can see, the script will now try to enable those Programs that it found and since we added the Verbose parameter we’ll see the output of each Program that it enabled.

I hope this helps you with migrating Packages and their Programs!

Nickolaj Andersen
Principal Consultant and Enterprise Mobility MVP since 2016. Nickolaj has been in the IT industry for the past 10 years specializing in Enterprise Mobility and Security, Windows devices and deployments including automation. Currently working for TrueSec as a Principal Consultant. Awarded as PowerShell Hero in 2015 by the community for his script and tools contributions. Creator of ConfigMgr Prerequisites Tool, ConfigMgr OSD FrontEnd, ConfigMgr WebService to name a few. Frequent speaker at conferences and user groups.


There are no comments.

Leave a Reply