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"
That’s all! The packages have now been removed, including their associated Deployments and Programs.
How to save the packages in the txt file? Can you give a example?
Package’s name in each line.