Remove multiple Packages in ConfigMgr 2012 with PowerShell

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 = ""
$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:

Removes packages in Configuration Manager 2012, specified from a text file.
This script will remove all packages matched by name specified in a text file.
Primary Site server name
Path to a text file containing package names
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"
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
This script requires proper permissions in Configuration Manager to remove the packages.

[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"

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


Nickolaj Andersen

Chief Technical Architect 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. 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 such as Microsoft Ignite, NIC Conference and IT/Dev Connections including nordic user groups.