Skip to content

Detect and remove application from dependent task sequences with PowerShell

I believe most of us use install application steps during operating system deployment, unless you are using fully dynamic scripts to install applications. We often do changes in our task sequence, we made a copy of the original task sequence, made it as backup, then start modify the new ones. In some point, we updated some of applications, and we might want to delete those old applications, but oops, cannot delete, because of number of dependent task sequences is not 0.

This popup message doesn’t tell what are the dependent task sequences, it is not so easy to find out which task sequence it is. Luckily we have PowerShell. Here is a very simple PowerShell script can do it for you.

# Site configuration
$ApplicationName = "7-zip" #Name of the application
$SiteServer = "CM01.ZIT.local" #Your site server name
$SiteCode ="T01" #Your site code

# Customizations
$initParams = @{}

# Import the ConfigurationManager.psd1 module 
if((Get-Module ConfigurationManager) -eq $null) {
    Import-Module "$($ENV:SMS_ADMIN_UI_PATH)\..\ConfigurationManager.psd1" @initParams 
}

# Connect to the site's drive if it is not already present
if((Get-PSDrive -Name $SiteCode -PSProvider CMSite -ErrorAction SilentlyContinue) -eq $null) {
    New-PSDrive -Name $SiteCode -PSProvider CMSite -Root $ProviderMachineName @initParams
}

# Set the current location to be the site code.
Set-Location "$($SiteCode):\" @initParams

#Get SMS_ApplicationLatest WMI object
$Application = Get-CMApplication -Name "$ApplicationName"

#Get Application Model Names
$ApplicationModelName = $Application.ModelName
$TaskSequencePackageIDs = (Get-WmiObject -Namespace "root\SMS\site_$($SiteCode)" -Class "SMS_TaskSequenceAppReferencesInfo" -ComputerName $SiteServer -Filter "RefAppModelName like '$ApplicationModelName'").PackageID
foreach ($TaskSequencePackageId in $TaskSequencePackageIds)
{
    $TaskSquenceName = (Get-CMTaskSequence -TaskSequencePackageId $TaskSequencePackageId).Name
    Write-host "Application name: $($Application.LocalizedDisplayName). Dependent TaskSequence is: $TaskSquenceName." -ForegroundColor Green
}

 

If you want to run this remotely without using Configuration Manager cmdlets, can use this script as well:

$ApplicationName = "7-zip" #Name of the application
$SiteServer = "CM01.ZIT.local" #Your site server name
$SiteCode ="T01" #Your site code

#Get SMS_ApplicationLatest WMI object
$Application = Get-WmiObject -Namespace "root\SMS\site_$($SiteCode)" -Class "SMS_ApplicationLatest" -ComputerName $SiteServer -Filter "LocalizedDisplayName='$ApplicationName' and IsExpired='False' "

Write-host "------------------------------------------------------" -ForegroundColor Green
Write-host "Application name: $($Application.LocalizedDisplayName)"  -ForegroundColor Green

#Get Application Model Names
$ApplicationModelName = $Application.ModelName

#Get SMS_TaskSequenceAppReferencesInfo WMI Object
$TaskSequencePackageIDs = (Get-WmiObject -Namespace "root\SMS\site_$($SiteCode)" -Class "SMS_TaskSequenceAppReferencesInfo" -ComputerName $SiteServer -Filter "RefAppModelName Like '$ApplicationModelName'").PackageID
Foreach ($TaskSequencePackageId in $TaskSequencePackageIds) 
{
    # Get SMS_TaskSequencePackage WMI object
    $TaskSequencePackage = Get-WmiObject -Namespace "root\SMS\site_$($SiteCode)" -Class SMS_TaskSequencePackage -ComputerName $SiteServer -Filter "PackageID like '$TaskSequencePackageId'"
    $TaskSequencePackage.Get()
            
    #Get Task SequenceName
    $TaskSquenceName = $TaskSequencePackage.Name
    Write-host "-----" -ForegroundColor Green 
    Write-host "Dependent TaskSequence is: $TaskSquenceName" -ForegroundColor Green    
    
    # Get SMS_TaskSequence WMI object from TaskSequencePackage
    $TaskSequence = Invoke-WmiMethod -Namespace "root\SMS\site_$($SiteCode)" -Class SMS_TaskSequencePackage -ComputerName $SiteServer -Name "GetSequence" -ArgumentList $TaskSequencePackage
    
    # Convert WMI object to XML
    $TaskSequenceResult = Invoke-WmiMethod -Namespace "root\SMS\site_$($SiteCode)" -Class SMS_TaskSequence -ComputerName $SiteServer -Name "SaveToXml" -ArgumentList $TaskSequence.TaskSequence
    [xml]$TaskSequenceXML = $TaskSequenceResult.ReturnValue 

    # Amend command line for Install other applications, only remove those applications that we don't want
    $InstallApplicationCommandLineNodes = Select-Xml -Xml $TaskSequenceXML -XPath "//step[contains(@type,'SMS_TaskSequence_InstallApplicationAction')]"
    foreach ($InstallApplicationCommandLineNode in $InstallApplicationCommandLineNodes)
    {
        if ($InstallApplicationCommandLineNode.Node.action -match $ApplicationModelName) {
            Write-host "Step name is: $($InstallApplicationCommandLineNode.Node.name) " -ForegroundColor Green
        }
    }
}

 

Finally, this script will remove the application from dependent task sequences, it use same technique as Nickolaj’s post Modify Task Sequence steps in ConfigMgr with PowerShell , please read Nickolaj’s post for reference.

$ApplicationName = "7-zip-copy" #Name of the application
$SiteServer = "CM01.ZIT.local" #Your site server name
$SiteCode ="T01" #Your site code

#Get SMS_ApplicationLatest WMI object
$Application = Get-WmiObject -Namespace "root\SMS\site_$($SiteCode)" -Class "SMS_ApplicationLatest" -ComputerName $SiteServer -Filter "LocalizedDisplayName='$ApplicationName' and IsExpired='False' "


Write-host "------------------------------------------------------" -ForegroundColor Green
Write-host "Application name: $($Application.LocalizedDisplayName)"  -ForegroundColor Green

#Get Application Model Names
$ApplicationModelName = $Application.ModelName

#Get SMS_TaskSequenceAppReferencesInfo WMI Object
$TaskSequencePackageIDs = (Get-WmiObject -Namespace "root\SMS\site_$($SiteCode)" -Class "SMS_TaskSequenceAppReferencesInfo" -ComputerName $SiteServer -Filter "RefAppModelName Like '$ApplicationModelName'").PackageID
Foreach ($TaskSequencePackageId in $TaskSequencePackageIds) 
{
    # Get SMS_TaskSequencePackage WMI object
    $TaskSequencePackage = Get-WmiObject -Namespace "root\SMS\site_$($SiteCode)" -Class SMS_TaskSequencePackage -ComputerName $SiteServer -Filter "PackageID like '$TaskSequencePackageId'"
    $TaskSequencePackage.Get()
            
    #Get Task SequenceName
    $TaskSquenceName = $TaskSequencePackage.Name
    Write-host "-----" -ForegroundColor Green 
    Write-host "Dependent TaskSequence is: $TaskSquenceName" -ForegroundColor Green    
    
    # Get SMS_TaskSequence WMI object from TaskSequencePackage
    $TaskSequence = Invoke-WmiMethod -Namespace "root\SMS\site_$($SiteCode)" -Class SMS_TaskSequencePackage -ComputerName $SiteServer -Name "GetSequence" -ArgumentList $TaskSequencePackage
    
    # Convert WMI object to XML
    $TaskSequenceResult = Invoke-WmiMethod -Namespace "root\SMS\site_$($SiteCode)" -Class SMS_TaskSequence -ComputerName $SiteServer -Name "SaveToXml" -ArgumentList $TaskSequence.TaskSequence
    [xml]$TaskSequenceXML = $TaskSequenceResult.ReturnValue 

    # Amend variable for Install applications, only remove those applications that we don't want
    $InstallApplicationVariableNodes = Select-Xml -Xml $TaskSequenceXML -XPath "//variable[contains(@name,'ApplicationName')]"
    foreach ($InstallApplicationVariableNode in $InstallApplicationVariableNodes) 
    {
        $InstallApplicationVariableNode.Node.'#text' = $InstallApplicationVariableNode.Node.'#text' -replace "$ApplicationModelName,", "" -replace ",$ApplicationModelName", "" -replace "$ApplicationModelName", ""
    }

    # Amend command line for Install other applications, only remove those applications that we don't want
    $InstallApplicationCommandLineNodes = Select-Xml -Xml $TaskSequenceXML -XPath "//step[contains(@type,'SMS_TaskSequence_InstallApplicationAction')]"
    foreach ($InstallApplicationCommandLineNode in $InstallApplicationCommandLineNodes)
    {
        if ($InstallApplicationCommandLineNode.Node.action -match $ApplicationModelName) {
        $InstallApplicationCommandLineNode.Node.action = $InstallApplicationCommandLineNode.Node.action -replace "$ApplicationModelName,", "" -replace ",$ApplicationModelName", "" -replace "$ApplicationModelName", ""
        Write-host "Step name is: $($InstallApplicationCommandLineNode.Node.name) " -ForegroundColor Green
        }
    }

    #Remove Application from Task Sequence step
    Try 
    {
        # Convert XML back to SMS_TaskSequencePackage WMI object
        $TaskSequenceResult = Invoke-WmiMethod -Namespace "root\SMS\site_$($SiteCode)" -Class SMS_TaskSequencePackage -ComputerName $SiteServer -Name "ImportSequence" -ArgumentList $TaskSequenceXML.OuterXml
        
        # Update SMS_TaskSequencePackage WMI object
        Invoke-WmiMethod -Namespace "root\SMS\site_$($SiteCode)" -Class SMS_TaskSequencePackage -ComputerName $SiteServer -Name "SetSequence" -ArgumentList @($TaskSequenceResult.TaskSequence, $TaskSequencePackage) | Out-Null
        Write-Host "Remove application $($Application.LocalizedDisplayName) from Task sequence $TaskSquenceName succeded" -ForegroundColor Yellow
    }
    catch 
    {
        Write-Host "Remove application $($Application.LocalizedDisplayName) from task sequence $TaskSquenceName failed .Error message: $($_.Exception.Message)" -ForegroundColor red
    }
}

IMPORTANT: As always, running any kind of script in your ConfigMgr server is dangerous without testing, so please do test these scripts in your testi environment before run it in production.

THE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND”

(Maybe we will make a GUI for this. Let’s see.. 😀 )

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.