ConfigMgr - Clear retired applications and content

Update
I made a tool out of this script as well, check it out!

Update 2022-03-04
Added options to export application and content, and/or save content at source
You know it's a pain, a bore, real tedious, but it has to be done.
Cleaning them old applications and their respective files.
It's a lot of clicking-about... zZzzZzzZZzZ
So, we create a new PowerShell function for it instead and let that handle it, you just have to mark you applications as "Retired" and this bad-boy will locate that sucker and eliminate it and all them files on your source share.
And, if you want, never worry about these things again by creating a scheduled task for it and let it go to town every other day, month or year, and you take your fishing gear and go to the lake instead. Just keep retiring them and then forget about it.
P.S If you wanna see them apps go down one-by-one instead, just specify what app you want gone with -SpecificApplication "NameOfAppToDelete".
And if your feeling anxious about firing away, use the -WhatIf switch to predict the future of your applications demise.
Otherwise this gets ALL your applications which is set at Retired, if you don´t use "$SpecificApplication", then gets the content location from the SDMPackgeXML (the XML information about your application), deletes the content, then deletes the app.
Note that the function can be run with -WhatIf, so that you first can check what will be deleted.
<#
.SYNOPSIS
This is is the script version of "Delete-RetiredApplications"-tool you can use if you dont care about saving any content or exporting/backing up your retired applications.
Use it with eg scheduled task or run on demand.
.VERSION
2022-02-03 - script created with basic function to clear all retired applications and their content
2022-03-04 - Added the options to have applicaiton exported before deletion, and/or save source content.
.EXAMPLE
Remove all you retired applications and their content
Remove-RetiredApplications -ProviderMachineName "cm01.corp.viamonstra.com" -SiteCode "PS1"
Remove specific application and its content
Remove-RetiredApplications -SpecificApplication "ApplicationName" -ProviderMachineName "cm01.corp.viamonstra.com" -SiteCode "PS1"
Export application and related content before deletion and ignore related applications
Remove-RetiredApplications -ProviderMachineName "cm01.corp.viamonstra.com" -SiteCode "PS1" -ExportApplication $true -OmitContent $false -IgnoreRelated $true -ExportLocation "$env:SYSTEMDRIVE\Temp\ApplicationArchive"
Save source content and delete applications
Remove-RetiredApplications -ProviderMachineName "cm01.corp.viamonstra.com" -SiteCode "PS1" -SaveContent $true
#>
Function Remove-RetiredApplications{
[cmdletbinding(SupportsShouldProcess=$True)]
Param(
[Parameter(Mandatory=$true, HelpMessage='Siteserver FQDN, eg cm01.corp.viamonstra.com')]
[string]$ProviderMachineName,
[Parameter(Mandatory=$true, HelpMessage='Sitecode, eg PS1')]
[string]$SiteCode,
[Parameter(HelpMessage='If you want to retire just a specific ')]
[string]$SpecificApplication,
[Parameter(Mandatory=$True,
ParameterSetName='ExportApplication',
HelpMessage='Set if you want the application to be exported before deletion.')]
[bool]$ExportApplication,
[Parameter(ParameterSetName='ExportApplication',
HelpMessage='Indicates that the cmdlet exports related content to a separate folder in the same location as the .zip file.')]
[bool]$OmitContent,
[Parameter(ParameterSetName='ExportApplication',
HelpMessage='Indicates that related objects, such as application dependencies, superseded applications, or related categories and global conditions, are not exported.')]
[bool]$IgnoreRelated,
[Parameter(HelpMessage='Set the location where you want app exported to.')]
[string]$ExportLocation,
[Parameter(Mandatory=$True, HelpMessage='Dont delete source content.')]
[bool]$SaveContent
)
begin{
# Load ConfigMgr PSModule and connect to site
if((Get-Module ConfigurationManager) -eq $null){
Import-Module "$($ENV:SMS_ADMIN_UI_PATH)\..\ConfigurationManager.psd1"
}
if((Get-PSDrive -Name $SiteCode -PSProvider CMSite -ErrorAction SilentlyContinue) -eq $null){
New-PSDrive -Name $SiteCode -PSProvider CMSite -Root $ProviderMachineName
}
# Get retired applications
Set-Location "$($SiteCode):\"
$AppLocations = @()
If([string]::IsNullOrEmpty($SpecificApplication)){
$RetiredApplications = Get-CMApplication -Fast | Where -Property IsExpired -eq "True" | Select -Property CI_ID,LocalizedDisplayName
}
Else{
$RetiredApplications = Get-CMApplication -Name $SpecificApplication
}
# Get application content location
Foreach($RetiredApplication in $RetiredApplications){
$App = Get-CMApplication -ID $RetiredApplication.CI_ID
$AppXML = [xml]$App.SDMPackageXML
$AppLocations += $AppXML.AppMgmtDigest.DeploymentType.Installer.Contents.Content.Location
}
}
Process{
# Export Application
Switch($ExportApplication){
"true"{
If (!(Test-path $ExportLocation)) {
New-Item -ItemType Directory -Path $ExportLocation -Force
}
Try {
Foreach ($RetiredApplication in $RetiredApplications ){
$Arguments = @{}
switch ($OmitContent) {
"true" { $Arguments += @{OmitContent = $true} }
}
switch ($IgnoreRelated) {
"true" { $Arguments += @{IgnoreRelated = $true} }
}
$AppArchiveDir = (New-Item -ItemType Directory -Force -Path "$ExportLocation\$($RetiredApplication.LocalizedDisplayName)").FullName
Export-CMApplication -Id $RetiredApplication.CI_ID -Path ($AppArchiveDir + "\" + ($RetiredApplication.LocalizedDisplayName) + ".zip") @Arguments -Force
}
}
Catch {
$_.Exception.Message
}
}
}
# Delete application contentfiles
Switch($SaveContent){
"False"{
Foreach($AppLocation in $AppLocations){
Write-Output "Removing Application content from $Applocation"
Set-Location $env:systemdrive
Remove-Item -Path $AppLocation -Recurse -Force
}
}
}
}
End{
# Delete the application from ConfigMgr
Foreach($RetiredApplication in $RetiredApplications){
Set-Location "$($SiteCode):\"
Remove-CMApplication -ID $RetiredApplication.CI_ID -Force
}
}
}
Example
Remove all you retired applications and content
Remove-RetiredApplications -ProviderMachineName "cm01.corp.viamonstra.com" -SiteCode "PS1"
Remove specific application and content
Remove-RetiredApplications -SpecificApplication "ApplicationName" -ProviderMachineName "cm01.corp.viamonstra.com" -SiteCode "PS1"
Export application and content, then remove
Remove-RetiredApplications -ProviderMachineName "cm01.corp.viamonstra.com" -SiteCode "PS1" -ExportApplication $true -OmitContent $false -IgnoreRelated $true -ExportLocation "$env:SYSTEMDRIVE\Temp\ApplicationArchive"
Save Content at source, remove application
Remove-RetiredApplications -ProviderMachineName "cm01.corp.viamonstra.com" -SiteCode "PS1" -SaveContent $true
Remember the -WhatIf
Remove-RetiredApplications -SpecificApplication "ApplicationName" -ProviderMachineName "cm01.corp.viamonstra.com" -SiteCode "PS1" -WhatIf
