PowerShell Script to Delete Apps, Packages + more

Photo of author
By Jeff LeBlanc

Use this script to delete a list of Apps, Packages, Task Sequences or Driver Packages that have been moved into a “Containment” state. See my other post for more information on objects in Containment at PowerShell Script to Move App/Package Content to Containment.

If you don’t use a Containment process, you will need to tweak some lines within this script as it looks for the word “Containment” to be in the app/package comment/description before it will delete it.

Just remove that check (Where-Object { $_.LocalizedDescription -Like ‘Containment‘ }) throughout the script if you don’t need it and you should be good to go.

###########################################################################################################
#
#  Script Name:      DeleteCMContent_v1.0.ps1  
#
#  Description:      Deletes a list of Applications/Packages/Driver Packages from SCCM
#
#  Authors:          Jeff LeBlanc
#
#  Version History:  1.0 - Initial Script
#
#  Command Lines:    .\DeleteCMContent_v1.0.ps1 -ApplicationsFile .\Applications.txt
#                    .\DeleteCMContent_v1.0.ps1 -PackagesFile .\Packages.txt
#                    .\DeleteCMContent_v1.0.ps1 -DriverPackagesFile .\DriverPackages.txt
#                    .\DeleteCMContent_v1.0.ps1 -TaskSequencesFile .\TaskSequences.txt
#                    .\DeleteCMContent_v1.0.ps1 -AppName .\Applications.txt
#                    .\DeleteCMContent_v1.0.ps1 -PackageID .\Packages.txt
#                    .\DeleteCMContent_v1.0.ps1 -DriverPackageID .\DriverPackages.txt
#                    .\DeleteCMContent_v1.0.ps1 -TaskSequenceID .\TaskSequences.txt
#  
###########################################################################################################

# Verify Command Line Parameters
[CmdletBinding()]
param(
    #Specify the App Name you want to put into Containment
    [parameter(Mandatory=$false)]
    $AppName,

    #Specify the PackageID that you want to put into Containment
    [parameter(Mandatory=$false)]
    $PackageID,

    #Specify the Driver Package ID that you want to put into Containment
    [parameter(Mandatory=$false)]
    $DriverPackageID,

    #Specify the Task Sequence PackageID that you want to put into Containment
    [parameter(Mandatory=$false)]
    $TaskSequenceID,

    #Specify the App Names you want to put into Containment
    [parameter(Mandatory=$false)]
    $ApplicationsFile,

    #Specify the Package IDs you want to put into Containment
    [parameter(Mandatory=$false)]
    $PackagesFile,

    #Specify the Driver Package IDs you want to put into Containment
    [parameter(Mandatory=$false)]
    $DriverPackagesFile,

    #Specify the Task Sequence Package IDs you want to put into Containment
    [parameter(Mandatory=$false)]
    $TaskSequencesFile
)

# Setup Log File Path
$SMSLogPath = $PSScriptRoot
$global:LogFile = "$SMSLogPath\DeleteCMContent.log"

Function Connect-Drive ($CASSiteCode, $CASSiteServer) {
    #Load the Configuration Manager Module
    Import-Module $env:SMS_ADMIN_UI_PATH.Replace("\bin\i386","\bin\ConfigurationManager.psd1")
    $CMDrive = Get-PSDrive -Name $CASSiteCode -ErrorAction Ignore

    # Connect to CMDrive
    if ($CMDrive)
    {
        Set-Location $CASSiteCode":"
    }
    else
    {
        $i = 1

        Do {
            Write-Host "Loop $i"
            $NewDrive = New-PSDrive -Name $CASSiteCode -PSProvider "CMSite" -Root $CASSiteServer -Scope Global
            $i++
        }
        Until ($NewDrive -ne $null -or $i -gt 10)
        Set-Location $CASSiteCode":"
    }
}


Function Get-Domain {
    $CompInfo = Get-WmiObject -Namespace root\cimv2 -Class Win32_ComputerSystem | Select Name, Domain
    Return $CompInfo.Domain.ToUpper()
}


Function Log-Write {

##########################################################################################################
<#
.SYNOPSIS
   Log to a file in a format that can be read by Trace32.exe / CMTrace.exe 

.DESCRIPTION
   Write a line of data to a script log file in a format that can be parsed by Trace32.exe / CMTrace.exe

   The severity of the logged line can be set as:

        1 - Information
        2 - Warning
        3 - Error

   Warnings will be highlighted in yellow. Errors are highlighted in red.

   The tools to view the log:

   SMS Trace - http://www.microsoft.com/en-us/download/details.aspx?id=18153
   CM Trace - Installation directory on Configuration Manager Site Server - <Install Directory>\Tools\

.EXAMPLE
   Log-Write c:\output\update.log "Application of MS15-031 failed" Apply_Patch 3

   This will write a line to the update.log file in c:\output stating that "Application of MS15-031 failed".
   The source component will be Apply_Patch and the line will be highlighted in red as it is an error 
   (severity - 3).

#>
##########################################################################################################

#Define and validate parameters
[CmdletBinding()]
Param(
      #Path to the log file
      [parameter(Mandatory=$True)]
      [String]$NewLog,

      #The information to log
      [parameter(Mandatory=$True)]
      [String]$Value,

      #The source of the error
      [parameter(Mandatory=$True)]
      [String]$Component,

      #The severity (1 - Information, 2- Warning, 3 - Error)
      [parameter(Mandatory=$True)]
      [ValidateRange(1,3)]
      [Single]$Severity
)


#Obtain UTC offset
$DateTime = New-Object -ComObject WbemScripting.SWbemDateTime 
$DateTime.SetVarDate($(Get-Date))
$UtcValue = $DateTime.Value
$UtcOffset = $UtcValue.Substring(21, $UtcValue.Length - 21)


#Create the line to be logged
$LogLine =  "<![LOG[$Value]LOG]!>" +`
            "<time=`"$(Get-Date -Format HH:mm:ss.fff)$($UtcOffset)`" " +`
            "date=`"$(Get-Date -Format M-d-yyyy)`" " +`
            "component=`"$Component`" " +`
            "context=`""" " +`
            "type=`"$Severity`" " +`
            "thread=`" " +`
            "file=`"`">"

#Write the line to the passed log file
Add-Content -Path $NewLog -Value $LogLine

}


Function DisplayUsage {
    Write-Host ""
    Write-Host "Usage Examples:" -ForegroundColor Green
    Write-Host "     .\DeleteCMContent.ps1 -AppName 'My Application Name'" -ForegroundColor Green
    Write-Host "     .\DeleteCMContent.ps1 -PackageID 'ABC00000'" -ForegroundColor Green
    Write-Host "     .\DeleteCMContent.ps1 -DriverPackageID 'ABC00123'" -ForegroundColor Green
    Write-Host "     .\DeleteCMContent.ps1 -TaskSequenceID 'ABC00123'" -ForegroundColor Green
    Write-Host "     .\DeleteCMContent.ps1 -ApplicationsFile .\Applications.txt" -ForegroundColor Green
    Write-Host "     .\DeleteCMContent.ps1 -PackagesFile .\Packages.txt" -ForegroundColor Green
    Write-Host "     .\DeleteCMContent.ps1 -DriverPackagesFile .\DriverPackages.txt" -ForegroundColor Green
    Write-Host "     .\DeleteCMContent.ps1 -TaskSequencesFile .\TaskSequences.txt" -ForegroundColor Green

    Set-Location $PSScriptRoot
    Exit(-1)
}


##########################################################################################################
#
#   MAIN SCRIPT
#
##########################################################################################################

# Start Timer
$processTimer = [System.Diagnostics.Stopwatch]::StartNew()

Write-Host "Starting Script Execution..." -ForegroundColor Cyan
Log-Write $LogFile "Starting Script Execution..." DeleteCMContent 1

# Get Domain
Write-Host "Getting Domain environment..." -ForegroundColor Gray
Log-Write $LogFile "Getting Domain environment..." DeleteCMContent 1
$Domain = Get-Domain


# Setup Site Code and Site Server Based on Domain
Switch ($Domain) {
    DEV-DOMAIN.COM {
        $CASSiteCode = "DEV"
        $CASSiteServer = "<ServerFQDN>"

        Write-Host "Domain: $Domain"
        Write-Host "Using CASSiteCode $CASSiteCode"
        Write-Host "Using CASSiteServer $CASSiteServer"

        Log-Write $LogFile "Domain: $Domain" DeleteCMContent 1
        Log-Write $LogFile "Using CASSiteCode $CASSiteCode" DeleteCMContent 1
        Log-Write $LogFile "Using CASSiteServer $CASSiteServer" DeleteCMContent 1
    }
    UAT-DOMAIN.COM {
        $CASSiteCode = "UAT"
        $CASSiteServer = "<ServerFQDN>"

        Write-Host "Domain: $Domain"
        Write-Host "Using CASSiteCode $CASSiteCode"
        Write-Host "Using CASSiteServer $CASSiteServer"

        Log-Write $LogFile "Domain: $Domain" DeleteCMContent 1
        Log-Write $LogFile "Using CASSiteCode $CASSiteCode" DeleteCMContent 1
        Log-Write $LogFile "Using CASSiteServer $CASSiteServer" DeleteCMContent 1
    }
    PROD-DOMAIN.COM {
        $CASSiteCode = "PRD"
        $CASSiteServer = "<ServerFQDN>"

        Write-Host "Domain: $Domain"
        Write-Host "Using CASSiteCode $CASSiteCode"
        Write-Host "Using CASSiteServer $CASSiteServer"

        Log-Write $LogFile "Domain: $Domain" DeleteCMContent 1
        Log-Write $LogFile "Using CASSiteCode $CASSiteCode" DeleteCMContent 1
        Log-Write $LogFile "Using CASSiteServer $CASSiteServer" DeleteCMContent 1
    }
    default {
        Write-Host "No supported Domain found. Exiting script." -ForegroundColor Red
        Log-Write $LogFile "No supported Domain found. Exiting script." DeleteCMContent 1

        Set-Location $PSScriptRoot
        Exit(-1)
    }
}


# Connect to CM Drive
Connect-Drive $CASSiteCode $CASSiteServer


# Check for AppName or PackageID or $TaskSequenceID or $DriverPackageID or ApplicationsFile or PackagesFile or Driver Packages File or Task SequencesFile Parameter
if ($AppName -or $PackageID -or $DriverPackageID -or $TaskSequenceID -or $ApplicationsFile -or $PackagesFile -or $DriverPackagesFile -or $TaskSequencesFile) {

    Write-Host "Application Name, PackageID, DriverPackageID, TaskSequenceID or file(s) found. Start processing..."
    Log-Write $LogFile "Application Name, PackageID, DriverPackageID, TaskSequenceID or file(s) found. Start processing..." DeleteCMContent 1

    # Process Application
    if ($AppName) {

        # Get Application Information
        $AppInfo = Get-CMApplication -Name $AppName

        Write-Host "Processing Application $AppName [$($AppInfo.PackageID)]" -ForegroundColor Green
        Log-Write $LogFile "Processing Application $AppName [$($AppInfo.PackageID)]" DeleteCMContent 1

        $bIsInUse = $false

        if ($AppInfo) {
            # Check if app is still in use:
            $bIsInUse = ($($AppInfo.NumberOfDependentTS -gt 0) -or $($AppInfo.NumberOfDeployments -gt 0))
        
            if($bIsInUse -eq $true) {
                Write-Host "$($AppInfo.LocalizedDisplayName) has $($AppInfo.NumberOfDeployments) Active Deployments and/or $($AppInfo.NumberOfDependentTS) task sequence assingments. Skipping..." -ForegroundColor Yellow
                Log-Write $LogFile "$($AppInfo.LocalizedDisplayName) has $($AppInfo.NumberOfDeployments) Active Deployments and/or $($AppInfo.NumberOfDependentTS) task sequence assingments. Skipping..." DeleteCMContent 2
            }
            else {
                # Delete the Application
                Write-Host "Deleting Application $AppName [$($AppInfo.PackageID)]" -ForegroundColor Gray
                Log-Write $LogFile "Deleting Application $AppName [$($AppInfo.PackageID)]" DeleteCMContent 1

                Get-CMApplication -Name $AppName | Where-Object { $_.LocalizedDescription -Like '*Containment*' } | Remove-CMApplication -Force -WhatIf
            }
        }
        else {
            Write-Host "No application object with name $AppName found in SCCM. Please specify a valid Application name." -ForegroundColor Red
            Log-Write $LogFile "No application object with name $AppName found in SCCM. Please specify a valid Application name." DeleteCMContent 1
        }
    } # End Process Application


    # Process Package
    if ($PackageID) {

        # Get Package Information
        $PkgInfo = Get-CMPackage -Id $PackageID -Fast

        Write-Host "Processing Package $($PkgInfo.Name) [$PackageID]" -ForegroundColor Green
        Log-Write $LogFile "Processing Package $($PkgInfo.Name) [$PackageID]" DeleteCMContent 1

        $bIsInUse = $false

        if ($PkgInfo) {
            # Get Task Sequence Information
            Write-Host "Getting Task Sequence information. This will take a minute..." -ForegroundColor Cyan
            Log-Write $LogFile "Getting Task Sequence information. This will take a minute..." DeleteCMContent 1

            $TaskSequences = Get-CMTaskSequence -Fast -ErrorAction SilentlyContinue | Where-Object { $_.References -ne $null }

            # Continue Package Processing
            $Deployments = ($PkgInfo | Get-CMPackageDeployment -ErrorAction SilentlyContinue)
            $TSReferences = ($TaskSequences | Where {$_.References.Package -eq $PkgInfo.PackageID})

            if (($Deployments.Count -gt 0) -or (($TSReferences | Measure-Object).Count -gt 0)) {        
                $bIsInUse = $true
            }

            if($bIsInUse -eq $true) {
                Write-Host "$($PkgInfo.Name) has $($Deployments.Count) Active Deployments or $(($TSReferences | Measure-Object).Count) TS References Found. Skipping..." -ForegroundColor Yellow
                Log-Write $LogFile "$($PkgInfo.Name) has $($Deployments.Count) Active Deployments or $(($TSReferences | Measure-Object).Count) TS References Found. Skipping..." DeleteCMContent 2
            }
            else {
                # Delete the Package
                Write-Host "Deleting package $PackageID" -ForegroundColor Green
                Get-CMPackage -Id $PackageID -Fast | Where-Object { $_.Description -Like 'Containment*' } | Remove-CMPackage -Force -WhatIf           
            }
        }
        else {
            Write-Host "No package object with PackageID $PackageID found in SCCM. Please enter a valid Package ID." -ForegroundColor Red
            Log-Write $LogFile "No package object with PackageID $PackageID found in SCCM. Please enter a valid Package ID." DeleteCMContent 3
        }
    } # End Process Packages


    # Process Driver Package
    if ($DriverPackageID) {

        # Get Driver Package Information
        $DrvPkgInfo = Get-CMDriverPackage -Id $DriverPackageID -Fast

        Write-Host "Processing Driver Package $($DrvPkgInfo.Name) [$DriverPackageID]" -ForegroundColor Green
        Log-Write $LogFile "Processing Driver Package $($DrvPkgInfo.Name) [$DriverPackageID]" DeleteCMContent 1

        $bIsInUse = $false

        if ($DrvPkgInfo) {
            # Get Task Sequence Information
            Write-Host "Getting Task Sequence information. This will take a minute..." -ForegroundColor Cyan
            Log-Write $LogFile "Getting Task Sequence information. This will take a minute..." DeleteCMContent 1

            $TaskSequences = Get-CMTaskSequence -Fast -ErrorAction SilentlyContinue | Where-Object { $_.References -ne $null }

            # Continue Driver Package Processing
            $TSReferences = ($TaskSequences | Where {$_.References.Package -eq $DrvPkgInfo.PackageID})

            if (($TSReferences | Measure-Object).Count -gt 0) {        
                $bIsInUse = $true
            }

            if($bIsInUse -eq $true) {
                Write-Host "$($DrvPkgInfo.Name) has $(($TSReferences | Measure-Object).Count) TS References Found. Skipping..." -ForegroundColor Yellow
                Log-Write $LogFile "$($DrvPkgInfo.Name) has $(($TSReferences | Measure-Object).Count) TS References Found. Skipping..." DeleteCMContent 2
            }
            else {
                # Delete the Driver Package
                Write-Host "Deleting Driver Package $DriverPackageID" -ForegroundColor Green
                Get-CMDriverPackage -Id $DriverPackageID -Fast | Where-Object { $_.Description -Like 'Containment*' } | Remove-CMDriverPackage -Force -WhatIf           
            }
        }
        else {
            Write-Host "No Driver Package object with PackageID $DriverPackageID found in SCCM. Please enter a valid Package ID." -ForegroundColor Red
            Log-Write $LogFile "No Driver Package object with PackageID $DriverPackageID found in SCCM. Please enter a valid Package ID." DeleteCMContent 3
        }
    } # End Process Driver Packages


    # Process Task Sequence
    if ($TaskSequenceID) {

        # Get Task Sequence Information
        $TSInfo = Get-CMTaskSequence -TaskSequencePackageId $TaskSequenceID -Fast

        Write-Host "Processing Task Sequence $($TSInfo.Name) [$TaskSequenceID]" -ForegroundColor Green
        Log-Write $LogFile "Processing Task Sequence $($TSInfo.Name) [$TaskSequenceID]" DeleteCMContent 1

        if ($TSInfo) {

            # Get All Task Sequence Information
            Write-Host "Getting Task Sequence information. This will take a minute..." -ForegroundColor Cyan
            Log-Write $LogFile "Getting Task Sequence information. This will take a minute..." DeleteCMContent 1

            $TaskSequences = Get-CMTaskSequence -Fast -ErrorAction SilentlyContinue | Where-Object { $_.References -ne $null }

            # Continue Task Sequence Processing
            $TSReferences = ($TaskSequences | Where {$_.References.Package -eq $TSInfo.PackageID})
            $Deployments = Get-CMTaskSequenceDeployment -TaskSequenceId $TaskSequenceID -Fast | Select-Object AdvertisementID

            if (($($Deployments.Count) -gt 0) -or ($TSReferences | Measure-Object).Count -gt 0) {        
                $bIsInUse = $true
            }

            if($bIsInUse -eq $true) {
                Write-Host "$($TSInfo.Name) has $($Deployments.Count) Active Deployments or $(($TSReferences | Measure-Object).Count) TS References Found. Skipping..." -ForegroundColor Yellow
                Log-Write $LogFile "$($TSInfo.Name) has $($Deployments.Count) Active Deployments or $(($TSReferences | Measure-Object).Count) TS References Found. Skipping..." DeleteCMContent 2
            }
            else {
                # Delete the Task Sequence
                Write-Host "Deleting Task Sequence $TaskSequenceID" -ForegroundColor Green
                Get-CMTaskSequence -Id $TaskSequenceID -Fast | Where-Object { $_.Description -Like 'Containment*' } | Remove-CMTaskSequence -Force -WhatIf           
            }
        }
        else {
            Write-Host "No Task Sequence object with PackageID $TaskSequenceID found in SCCM. Exiting." -ForegroundColor Red
            Log-Write $LogFile "No Task Sequence object with PackageID $TaskSequenceID found in SCCM. Exiting." DeleteCMContent 1
        }
    } # End Process Task Sequence



    # Process Applications File
    if ($ApplicationsFile) {
        
        Write-Host "Processing Applications found in $ApplicationsFile"
        Log-Write $LogFile "Processing Applications found in $ApplicationsFile" DeleteCMContent 1

        $Applications = Get-Content -Path $PSScriptRoot\$ApplicationsFile

        Write-Host "Found $($Applications.Count) Applications to process" -ForegroundColor Cyan
        Log-Write $LogFile "Found $($Applications.Count) Applications to process" DeleteCMContent 1

        ForEach ($Application in $Applications) {
            
            Write-Host "Getting $Application Application information..." -ForegroundColor Cyan
            Log-Write $LogFile "Getting $Application Application information" DeleteCMContent 1

            # Get Application Information
            $AppInfo = Get-CMApplication -Name $Application

            Write-Host "Processing Application $Application [$($AppInfo.PackageID)]" -ForegroundColor Green
            Log-Write $LogFile "Processing Application $Application [$($AppInfo.PackageID)]" DeleteCMContent 1

            $bIsInUse = $false

            if ($AppInfo) {
                # Check if app is still in use:
                $bIsInUse = ($($AppInfo.NumberOfDependentTS -gt 0) -or $($AppInfo.NumberOfDeployments -gt 0))
        
                if ($bIsInUse -eq $true) {
                    Write-Host "$($AppInfo.LocalizedDisplayName) has $($AppInfo.NumberOfDeployments) Active Deployments and/or $($AppInfo.NumberOfDependentTS) task sequence assingments. Skipping..." -ForegroundColor Yellow
                    Log-Write $LogFile "$($AppInfo.LocalizedDisplayName) has $($AppInfo.NumberOfDeployments) Active Deployments and/or $($AppInfo.NumberOfDependentTS) task sequence assingments. Skipping..." DeleteCMContent 2
                }
                else {
                    # Delete the Application
                    Write-Host "Deleting Application $Application [$($AppInfo.PackageID)]" -ForegroundColor Gray
                    Log-Write $LogFile "Deleting Application $Application [$($AppInfo.PackageID)]" DeleteCMContent 1

                    Get-CMApplication -Name $Application | Where-Object { $_.LocalizedDescription -Like '*Containment*' } | Remove-CMApplication -Force -WhatIf
                }
            }
            else {
                Write-Host "No application object with name $Application found in SCCM. Please specify a valid Application name." -ForegroundColor Red
                Log-Write $LogFile "No application object with name $Application found in SCCM. Please specify a valid Application name." DeleteCMContent 1
            }
        } # End for loop
    } # End Process ApplicationsFile


    # Process Packages File
    if ($PackagesFile) {
        Write-Host "Processing Packages found in $PackagesFile"
        Log-Write $LogFile "Processing Packages found in $PackagesFile" DeleteCMContent 1

        $Packages = Get-Content -Path $PSScriptRoot\$PackagesFile

        Write-Host "Found $($Packages.Count) packages to process"
        Log-Write $LogFile "Found $($Packages.Count) packages to process" DeleteCMContent 1

        # Get All Task Sequence References
        Write-Host "Getting all Task Sequence References from SCCM. Ignore the WARNING, we need the lazy properties. This will take a few moments..."
        Log-Write $LogFile "Getting all Task Sequence References from SCCM. Ignore the WARNING, we need the lazy properties. This will take a few moments..." DeleteCMContent 1

        $TaskSequences = Get-CMTaskSequence -ErrorAction SilentlyContinue | Where-Object { $_.References -ne $null }

        # Process Packages
        ForEach ($Package in $Packages) {
            Write-Host "Getting $Package package information..." -ForegroundColor Cyan
            Log-Write $LogFile "Getting $Package package information" DeleteCMContent 1

            # Get Package Information
            $PkgInfo = Get-CMPackage -Id $Package -Fast

            $bIsInUse = $false

            if ($PkgInfo) {
                Write-Host "Package $($PkgInfo.Name) [$Package] found." -ForegroundColor Green
                Log-Write $LogFile "Package $($PkgInfo.Name) [$Package] found." DeleteCMContent 1

                $Deployments = ($PkgInfo | Get-CMPackageDeployment -ErrorAction SilentlyContinue)
                $TSReferences = ($TaskSequences | Where {$_.References.Package -eq $PkgInfo.PackageID})

                if (($Deployments.Count -gt 0) -or (($TSReferences | Measure-Object).Count -gt 0)) {
                    $bIsInUse = $true
                }

                if($bIsInUse -eq $true) {
                    Write-Host "$($PkgInfo.Name) has $($Deployments.Count) Active Deployments or $(($TSReferences | Measure-Object).Count) TS References Found. Skipping..." -ForegroundColor Yellow
                    Log-Write $LogFile "$($PkgInfo.Name) has $($Deployments.Count) Active Deployments or $(($TSReferences | Measure-Object).Count) TS References Found. Skipping..." DeleteCMContent 2
                }
                else {
                    # Delete the Package
                    Write-Host "Deleting package $Package" -ForegroundColor Green
                    Log-Write $LogFile "Deleting package $Package" DeleteCMContent 1

                    Get-CMPackage -Id $Package -Fast | Where-Object { $_.Description -Like 'Containment*' } | Remove-CMPackage -Force -WhatIf
                }
            }
            else {
                Write-Host "No package object with PackageID $Package found in SCCM. Please enter a valid Package ID." -ForegroundColor Red
                Log-Write $LogFile "No package object with PackageID $Package found in SCCM. Please enter a valid Package ID." DeleteCMContent 3
            }
        } # End for loop
    } # End Process PackagesFile


    # Process Driver Packages File
    $i = 1

    if ($DriverPackagesFile) {
        Write-Host "Processing Driver Packages found in $DriverPackagesFile"
        Log-Write $LogFile "Processing Driver Packages found in $DriverPackagesFile" DeleteCMContent 1

        $DriverPackages = Get-Content -Path $PSScriptRoot\$DriverPackagesFile

        Write-Host "Found $($DriverPackages.Count) driver packages to process" -ForegroundColor Cyan
        Log-Write $LogFile "Found $($DriverPackages.Count) driver packages to process" DeleteCMContent 1

        # Get All Task Sequence References
        Write-Host "Getting all Task Sequence References from SCCM. Ignore the WARNING, we need the lazy properties for the TS references. This will take a few moments..." -ForegroundColor Yellow
        Log-Write $LogFile "Getting all Task Sequence References from SCCM. Ignore the WARNING, we need the lazy properties for the TS references. This will take a few moments..." DeleteCMContent 1

        $TaskSequences = Get-CMTaskSequence -ErrorAction SilentlyContinue | Where-Object { $_.References -ne $null }

        # Process Driver Packages
        ForEach ($DriverPackage in $DriverPackages) {
            Write-Host "$i. Getting $DriverPackage information..." -ForegroundColor Cyan
            Log-Write $LogFile "$i. Getting $DriverPackage information..." DeleteCMContent 1

            # Get Driver Package Information
            $DrvPkgInfo = Get-CMDriverPackage -Id $DriverPackage -Fast

            if ($DrvPkgInfo) {

                Write-Host "Found Driver Package $($DrvPkgInfo.Name) [$DriverPackage]." -ForegroundColor Green
                Log-Write $LogFile "Found Processing Driver Package $($DrvPkgInfo.Name) [$DriverPackage]." DeleteCMContent 1

                $bIsInUse = $false

                # Check TS References and Skip Driver Package if any are found
                Write-Host "Checking Task Sequence References..."
                Log-Write $LogFile "Checking Task Sequence References..." DeleteCMContent 1

                $TSReferences = ($TaskSequences | Where {$_.References.Package -eq $DrvPkgInfo.PackageID})

                if (($TSReferences | Measure-Object).Count -gt 0) {        
                    $bIsInUse = $true
                }

                if($bIsInUse -eq $true) {
                    Write-Host "$($DrvPkgInfo.Name) has $(($TSReferences | Measure-Object).Count) TS References Found. Skipping..." -ForegroundColor Yellow
                    Log-Write $LogFile "$($DrvPkgInfo.Name) has $(($TSReferences | Measure-Object).Count) TS References Found. Skipping..." DeleteCMContent 2
                }
                else {
                    # Delete the Driver Package
                    Write-Host "Deleting Driver Package $DriverPackage"
                    Log-Write $LogFile "Deleting Driver Package $DriverPackage" DeleteCMContent 1

                    Get-CMDriverPackage -Id $DriverPackage -Fast | Where-Object { $_.Description -Like 'Containment*' } | Remove-CMDriverPackage -Force        
                }
            }
            else {
                Write-Host "No Driver Package object with PackageID $DriverPackage found in SCCM. Please enter a valid Package ID." -ForegroundColor Red
                Log-Write $LogFile "No Driver Package object with PackageID $DriverPackage found in SCCM. Please enter a valid Package ID." DeleteCMContent 3
            }

            $i++
        } # End for loop
    } # End Process DriverPackagesFile


    # Process Task SequencesFile
    if ($TaskSequencesFile) {
        Write-Host "Processing Task Sequences in $TaskSequencesFile" -ForegroundColor Yellow
        Log-Write $LogFile "Processing Task Sequences in $TaskSequencesFile" RetireApplicationPackage 1

        # Read $TaskSequencesFile for TS List
        $TaskSequences = Get-Content $PSScriptRoot\$TaskSequencesFile

        Write-Host "Found $($TaskSequences.Count) Task Sequences to process" -ForegroundColor Yellow
        Log-Write $LogFile "Found $($TaskSequences.Count) Task Sequences to process" DeleteCMContent 1

        # Get All Task Sequence Information
        Write-Host "Getting Task Sequence information. This will take a minute..." -ForegroundColor Cyan
        Log-Write $LogFile "Getting Task Sequence information. This will take a minute..." DeleteCMContent 1

        $TaskSequences = Get-CMTaskSequence -Fast -ErrorAction SilentlyContinue | Where-Object { $_.References -ne $null }

        ForEach ($ts in $TaskSequences) {
            # Get Task Sequence Information
            $TSInfo = Get-CMTaskSequence -TaskSequencePackageId $ts -Fast

            if ($TSInfo) {
                Write-Host "Task Sequence $($TSInfo.Name) [$ts] found." -ForegroundColor Green
                Log-Write $LogFile "Task Sequence $($TSInfo.Name) [$ts] found." DeleteCMContent 1

                # Continue Task Sequence Processing
                $TSReferences = ($TaskSequences | Where {$_.References.Package -eq $TSInfo.PackageID})
                $Deployments = Get-CMTaskSequenceDeployment -TaskSequenceId $ts -Fast | Select-Object AdvertisementID

                if (($($Deployments.Count) -gt 0) -or ($TSReferences | Measure-Object).Count -gt 0) {        
                    $bIsInUse = $true
                }

                if($bIsInUse -eq $true) {
                    Write-Host "$($TSInfo.Name) has $($Deployments.Count) Active Deployments or $(($TSReferences | Measure-Object).Count) TS References Found. Skipping..." -ForegroundColor Yellow
                    Log-Write $LogFile "$($TSInfo.Name) has $($Deployments.Count) Active Deployments or $(($TSReferences | Measure-Object).Count) TS References Found. Skipping..." DeleteCMContent 2
                }
                else {
                    # Delete the Task Sequence
                    Write-Host "Deleting Task Sequence $ts" -ForegroundColor Green
                    Get-CMTaskSequence -Id $ts -Fast | Where-Object { $_.Description -Like 'Containment*' } | Remove-CMTaskSequence -Force -WhatIf
                }
            }
            else {
                Write-Host "No Task Sequence object with PackageID $ts found in SCCM. Exiting." -ForegroundColor Red
                Log-Write $LogFile "No Task Sequence object with PackageID $ts found in SCCM. Exiting." DeleteCMContent 1
            }
        } # End for loop
    } # End Process TaskSequencesFile
}
else {
    Write-Host "No Applications, Packages or Task Sequences or input files specified. Exiting." -ForegroundColor Red
    Log-Write $LogFile "No Applications, Packages or Task Sequences or input files specified. Exiting." DeleteCMContent 1

    DisplayUsage

    Set-Location $PSScriptRoot
    Exit(-1)
}

Write-Host "Finished script execution." -ForegroundColor Cyan
Log-Write $LogFile "Finished script execution." DeleteCMContent 1

$processTimer.Stop()
$processTimer.Elapsed

Set-Location $PSScriptRoot

Happy Computing!

Leave a Comment