Lately I’ve been involved in a migration project where the customer is moving from legacy Packages to the new Application Model. During our analysis we came to the conclusion that some packages would be left and not migrated to applications. When we had figured out which packages that were eligible for migration and migrated them, we had to remove all duplicate packages that now also was applications. One of the key steps that we took during the migration process was to keep the manufacturer, name and version of the package the same for the application. This really helps when you want to cross check what application has a duplicate package.

In order to come up with the list of applications that we had created during this migration, and not select those that the customer had tested with earlier, I used the following small PowerShell script:

$SiteServer = "CAS01.contoso.com"
$SiteCode = "CAS"
$DaysAgo = "5"
$Applications = Get-WmiObject -Namespace "root\SMS\site_$($SiteCode)" -Class SMS_ApplicationLatest
foreach ($Application in $Applications) {
    if ([System.Management.ManagementDateTimeConverter]::ToDateTime($Application.DateCreated) -ge (Get-Date).AddDays(-$($DaysAgo))) {
        Write-Output $Application.LocalizedDisplayName
    }
}

Now that we had a list of all the applications created, it’s time to remove the corresponding (or duplicate) packages. Here’s the script I used for that:

<#
.SYNOPSIS

Removes packages in Configuration Manager 2012, specified from a text file.

.DESCRIPTION

This script will remove all packages matched by name specified in a text file.

.PARAMETER SiteServer

Primary Site server name

.PARAMETER FilePath

Path to a text file containing package names

.EXAMPLE

Remove all packages that matches the name specified in a text file located at 'C:\Temp\Packages.txt' at the Primary Site server called 'CM01':

.\Remove-PackagesFromList.ps1 -SiteServer CM01 -FilePath "C:\Temp\Packages.txt"

.EXAMPLE 

Check what packages are to be removed specified in a text file located at 'C:\Temp\Packages.txt' at the Primary Site server called 'CM01':

.\Remove-PackagesFromList.ps1 -SiteServer CM01 -FilePath "C:\Temp\Packages.txt" -WhatIf

.NOTES

This script requires proper permissions in Configuration Manager to remove the packages.

#>
[CmdletBinding(SupportsShouldProcess=$true)]
param(
    [parameter(Mandatory=$true, HelpMessage="Specify Primary Site server")]
    [string]$SiteServer = "$($env:COMPUTERNAME)",
    [parameter(Mandatory=$true, HelpMessage="Path to text file")]
    [ValidateScript({Test-Path -Path $_ -Include *.txt})]
    [string]$FilePath
)
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
        foreach ($SiteCodeObject in $SiteCodeObjects) {
            if ($SiteCodeObject.ProviderForLocalSite -eq $true) {
                $SiteCode = $SiteCodeObject.SiteCode
                Write-Debug "SiteCode: $($SiteCode)"
            }
        }
    }
    catch [Exception] {
        Throw "Unable to determine SiteCode"
    }
    # Load the Configuration Manager 2012 PowerShell module
    try {
        Write-Verbose "Importing Configuration Manager module"
        Write-Debug ((($env:SMS_ADMIN_UI_PATH).Substring(0,$env:SMS_ADMIN_UI_PATH.Length-5)) + "\ConfigurationManager.psd1")
        Import-Module ((($env:SMS_ADMIN_UI_PATH).Substring(0,$env:SMS_ADMIN_UI_PATH.Length-5)) + "\ConfigurationManager.psd1") -Force
        if ((Get-PSDrive $SiteCode -ErrorAction SilentlyContinue | Measure-Object).Count -ne 1) {
            New-PSDrive -Name $SiteCode -PSProvider "AdminUI.PS.Provider\CMSite" -Root $SiteServer
        }
        # Set the location to the Configuration Manager drive
        Set-Location ($SiteCode + ":")
    }
    catch [Exception] {
        Throw $_.Exception.Message
    }
}
Process {
    try {
        # Get application names to look for
        $ApplicationNames = Get-Content -Path $FilePath
        #Write-Debug $ApplicationNames[0]
        foreach ($ApplicationName in $ApplicationNames) {
            $Package = Get-CMPackage -Name "$($ApplicationName)"
            if ($Package) {
                if ($Package.Count -ge 2) {
                    Write-Debug "Current Package:`n$($Package[0].Name)"
                    if ($Package[0].Name -like $ApplicationName) {
                        if ($PSCmdlet.ShouldProcess($Package[0].Name, "Remove")) {
                            Write-Verbose "Removing package: $($Package[0].Name)"
                            Remove-CMPackage -Name "$($Package[0].Name)" -Force -Verbose
                        }
                    }
                }
                else {
                    if ($Package.Name -like $ApplicationName) {
                        if ($PSCmdlet.ShouldProcess($Package.Name, "Remove")) {
                            Write-Verbose "Removing package: $($Package.Name)"
                            Remove-CMPackage -Name "$($Package.Name)" -Force -Verbose
                        }
                    }
                }
            }
            else {
                Write-Verbose "Unable to find '$($ApplicationName)'"
            }
        }
        Set-Location -Path C:
    }
    catch [Exception] {
        Write-Error $_.Exception.Message
    }
}

This script is built to support advanced PowerShell functions, such as -WhatIf, -Verbose and -Confirm. To use the script, simply save the list of applications in a text file and call it e.g. Apps.txt. Save the above script as Remove-PackagesFromList.ps1.

1. Open an elevated PowerShell console and browse to where you’ve saved the script.
2. Run the following command to see what the script will do:

.\Remove-PackagesFromList.ps1 -SiteServer CAS01 -FilePath "C:\Temp\Apps.txt" -WhatIf

3. Run the following command if you are ready to remove the packages:

.\Remove-PackagesFromList.ps1 -SiteServer CAS01 -FilePath "C:\Temp\Apps.txt"

109_1

That’s all! The packages have now been removed, including their associated Deployments and Programs.

Nickolaj Andersen
Principal Consultant and Enterprise Mobility MVP. Nickolaj has been in the IT industry for the past 10 years specializing in Enterprise Mobility and Security, Windows deployments and Automation. In 2015 Nickolaj was awarded as PowerShell Hero by the community for his script and tools contributions. Author of ConfigMgr Prerequisites Tool, ConfigMgr OSD FrontEnd, ConfigMgr WebService and a frequent speaker at user groups.

(203)

comments
  • Abel
    Posted at 16:56 June 16, 2016
    Abel
    Reply
    Author

    How to save the packages in the txt file? Can you give a example?

    • Abel
      Posted at 19:12 June 16, 2016
      Abel
      Reply
      Author

      Package’s name in each line.

  • Leave a Reply