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 when you have lots of them. Luckily we have PowerShell. Here is a very simple PowerShell script can do it for you. You can also import ConfigMgr PowerShell module what is mentioned in Jordan’s post How to import ConfigMgr powershell cmdlets

You can find this script from GitHub

# 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, use this script from GitHub.

 

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.

You will find the script from GitHub

 

IMPORTANT: As always, running any kind of script in your ConfigMgr server is dangerous without testing, so please do test these scripts in your test 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.. 😀 )

(5302)

comments
  • Dylan R Fullerton
    Posted at 04:05 December 9, 2018
    Dylan R Fullerton
    Reply
    Author

    Thank you so much for posting this. As a Senior SCCM Administrator managing (157) Distribution Points…..SCCONFIGMGR is the most helpful site on the Web. I can’t thank you all enough!

    • Zeng Yinghua
      Posted at 11:13 December 9, 2018
      Zeng Yinghua
      Reply
      Author

      That’s a lot of Distribution Points. 🙂 We are glad that we can help and share, thanks for supporting us!

  • Tim
    Posted at 20:47 February 4, 2019
    Tim
    Reply
    Author

    Thanks for this, it’s just what I need. The first script to show the dependent task sequences works flawlessly. I am running into an issue when I run the script to actually remove the applications from the TSes though. When trying to remove a particular app (in this case, an old version of Android Studio) I get something like:

    ——————————————————
    Application name: Android Studio 143.2915827
    —–
    Dependent TaskSequence is: Client Dev Win7x64
    Select-Xml : Cannot bind parameter ‘Xml’.

    …which is then followed by the xml for the entire TS that I’ll cut for brevity (but can post if needed), then ending with:

    ” value of type “System.String” to type “System.Xml.XmlNode”.
    At D:\SysAdmin\Scripts\SCCM\RemoveApplicationReferencedinTS.ps1:36 char:59
    + … pplicationCommandLineNodes = Select-Xml -Xml $TaskSequenceXML -XPath …
    + ~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidArgument: (:) [Select-Xml], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.SelectXmlCommand

    Invoke-WmiMethod : Generic failure
    At D:\SysAdmin\Scripts\SCCM\RemoveApplicationReferencedinTS.ps1:48 char:31
    + … nceResult = Invoke-WmiMethod -Namespace “root\SMS\site_$($SiteCode)” …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [Invoke-WmiMethod], ManagementException
    + FullyQualifiedErrorId : InvokeWMIManagementException,Microsoft.PowerShell.Commands.InvokeWmiMethod

    Invoke-WmiMethod : Generic failure
    At D:\SysAdmin\Scripts\SCCM\RemoveApplicationReferencedinTS.ps1:51 char:9
    + Invoke-WmiMethod -Namespace “root\SMS\site_$($SiteCode)” -Cla …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [Invoke-WmiMethod], ManagementException
    + FullyQualifiedErrorId : InvokeWMIManagementException,Microsoft.PowerShell.Commands.InvokeWmiMethod

    Remove application Android Studio 143.2915827 from Task sequence Client Dev Win7x64 succeded

    It repeats for the additional four TSes it finds the app in and doesn’t actually succeed. Anyone else run into anything similar?

    • Zeng Yinghua
      Posted at 20:29 February 5, 2019
      Zeng Yinghua
      Reply
      Author

      Hello, I just test that in my test lab, it still works without errors. When you run into errors, does it give you any values for $TaskSequence, $TaskSequenceResult, $TaskSequenceXML and $InstallApplicationVariableNodes? Looks like it failed in Select-Xml. Did you modified the script? Because in your error log Invoke-WmiMethod -Namespace “root\SMS\site_$($SiteCode) is in line 48 and 51, I have different line numbers in my original script. Can you post your script to OneDrive or any download location?

      • Tim
        Posted at 21:19 February 5, 2019
        Tim
        Reply
        Author

        Hi Zeng, thanks for your reply. I think the line numbers might be different because the formatting removed the blank lines when I originally copied the script over, but I haven’t edited any other way (at least not intentionally) apart from setting the variables at the top. I just copied it over again and I still seem to get the same error (albeit now with different line/character for that portion). By running ($Error[#]).InvocationInfo.Line (there’s probably a better way to do this) I could expand the error a bit and find errors at the following variables (including ones for $TaskSequenceResult and $InstallApplicationVariableNodes) but it doesn’t appear to provide me with much info. The only part I cut off in my earlier post just includes the XML for the TS (which I can’t attach without editing first due to it containing credentials in plain text):

        Invoke-WmiMethod -Namespace “root\SMS\site_$($SiteCode)” -Class SMS_TaskSequencePackage -ComputerName $SiteServer -Name “SetSequence” -ArgumentList @($TaskSequenceResult.TaskSequence, $TaskSequencePa
        ckage) | Out-Null

        $TaskSequenceResult = Invoke-WmiMethod -Namespace “root\SMS\site_$($SiteCode)” -Class SMS_TaskSequencePackage -ComputerName $SiteServer -Name “ImportSequence” -ArgumentList $TaskSequenceXML.OuterXml

        $InstallApplicationCommandLineNodes = Select-Xml -Xml $TaskSequenceXML -XPath “//step[contains(@type,’SMS_TaskSequence_InstallApplicationAction’)]”

        $InstallApplicationVariableNodes = Select-Xml -Xml $TaskSequenceXML -XPath “//variable[contains(@name,’ApplicationName’)]”

        Here’s a link to the script I’m running: https://onedrive.live.com/?authkey=%21APGeglw8zide5kM&cid=088783C0238CB2AD&id=88783C0238CB2AD%2112107&parId=88783C0238CB2AD%2112104&o=OneUp

        Incidentally we are currently on 1806 and upgrading tomorrow. Thanks again for the response!

        • Zeng Yinghua
          Posted at 22:37 February 13, 2019
          Zeng Yinghua
          Reply
          Author

          Hello Tim, sorry for the delay. Will you try what Yuchi suggested?

          • Tim
            Posted at 20:28 February 18, 2019
            Tim
            Author

            I apologize for my slow response, but I can confirm that Yuchi’s fix, adding [xml] to the $TaskSequenceXML variable, worked great (and as a bonus, I improved my Powershell skill a bit in the process of going through the script too, which is always welcome). And wow, what an elegant script it is.

            Thanks again for this incredibly helpful script and great blog. I don’t comment often but SCConfigMgr has helped me many times since we’ve implemented SCCM, and it’s very much appreciated.

          • Zeng Yinghua
            Posted at 23:59 February 18, 2019
            Zeng Yinghua
            Author

            Hello Tim, thanks for spotting out this issue and testing it. We are very happy that we have such strong community to help each other, thanks again for supporting us and your kindly comments.

      • Yuchi
        Posted at 17:01 February 13, 2019
        Yuchi
        Reply
        Author

        Thank you Zeng so much. I’m learning so much on your Website and this script is very useful. Thank you all @SCConfigMgr.

        I had the same error as Tim mention above. It seems to be the variable $TaskSequenceXML isn’t parsing the data as XML so I added the [XML] under the # Convert WMI object to XML section.

        $TaskSequenceXML = [xml]$TaskSequenceResult.ReturnValue

        • Zeng Yinghua
          Posted at 22:35 February 13, 2019
          Zeng Yinghua
          Reply
          Author

          Thank you Yuchi for you help! I will update my script. Glad to hear you like our blog!

        • Tim
          Posted at 20:30 February 18, 2019
          Tim
          Reply
          Author

          Yuchi, your fix worked great. Nice spot! Thanks for your help.

  • Ron
    Posted at 19:35 March 11, 2019
    Ron
    Reply
    Author

    Excellent post. Would it be possible to do a similar thing for Packages instead of Applications?
    I tried something like:
    $package = Get-CMPackage -Name “Google Chrome 71.0.1234.56”
    $TaskSequencePackageIDs = (Get-WmiObject -Namespace “root\SMS\site_$($SiteCode)” -Class “SMS_TaskSequenceAppRe
    ferencesInfo” -ComputerName $SiteServer -Filter “RefAppModelName like ‘$packageName'”).PackageID

    But $TaskSequencePackageIDs keeps coming back blank, even though I know the package I’m naming as a test exists in multiple task sequences.

  • Russ Ring
    Posted at 14:55 March 12, 2019
    Russ Ring
    Reply
    Author

    Question?… could the delete script be edited to “Replace” the app?

    so, if the TS has old flash XX that is now flash YY, can it delete XX and add YY to the TS?

    • Knobby
      Posted at 16:58 May 29, 2019
      Knobby
      Reply
      Author

      @Russ Ring
      Yep…. that’s what I’ve been working on (and I think cracked) in this script below. Hope it helps you or someone else, as this site has helped me no end.

      Script is bastardised from this one and elsewhere, then tweaked.

      Import-Module “$($ENV:SMS_ADMIN_UI_PATH)\..\ConfigurationManager.psd1” # Import the ConfigurationManager.psd1 module
      $CurrentLocation = get-location | select -ExpandProperty path # gets current user location
      Set-Location “AB1:” # Set the current location to be the site code.

      [array]$DropDownArrayItemsOLD = Get-CMApplication | select -ExpandProperty localizeddisplayname
      [array]$DropDownArrayOLD = $DropDownArrayItemsOLD | sort

      [array]$DropDownArrayItemsNEW = Get-CMApplication | select -ExpandProperty localizeddisplayname
      [array]$DropDownArrayNEW = $DropDownArrayItemsNEW | sort

      # This Function Returns the Selected Value and Closes the Form

      function Return-DropDown {
      if ($DropDownOLD.SelectedItem -eq $null -or $DropDownNew.SelectedItem -eq $null){
      $DropDownOLD.SelectedItem = $DropDownOLD.Items[0]
      $DropDownNEW.SelectedItem = $DropDownNEW.Items[0]
      $script:ChoiceOLD = $DropDownOLD.SelectedItem.ToString()
      $script:ChoiceNEW = $DropDownNEW.SelectedItem.ToString()
      $Form.Close()
      }
      else{
      $script:ChoiceOLD = $DropDownOLD.SelectedItem.ToString()
      $script:ChoiceNEW = $DropDownNEW.SelectedItem.ToString()
      $Form.Close()
      }
      }

      function SelectApplication{
      [void] [System.Reflection.Assembly]::LoadWithPartialName(“System.Windows.Forms”)
      [void] [System.Reflection.Assembly]::LoadWithPartialName(“System.Drawing”)

      $Form = New-Object System.Windows.Forms.Form

      $Form.width = 300
      $Form.height = 150
      $Form.Text = “Replace an Application in Dependant TS”

      $DropDownOLD = new-object System.Windows.Forms.ComboBox
      $DropDownOLD.Location = new-object System.Drawing.Size(100,10)
      $DropDownOLD.Size = new-object System.Drawing.Size(130,30)

      $DropDownNEW = new-object System.Windows.Forms.ComboBox
      $DropDownNEW.Location = new-object System.Drawing.Size(100,50)
      $DropDownNEW.Size = new-object System.Drawing.Size(130,30)

      ForEach ($Item in $DropDownArrayOLD) {
      [void] $DropDownOLD.Items.Add($Item)
      }

      ForEach ($Item in $DropDownArrayNEW) {
      [void] $DropDownNEW.Items.Add($Item)
      }

      $Form.Controls.Add($DropDownOLD)
      $Form.Controls.Add($DropDownNEW)

      $DropDownOLDLabel = new-object System.Windows.Forms.Label
      $DropDownOLDLabel.Location = new-object System.Drawing.Size(10,10)
      $DropDownOLDLabel.size = new-object System.Drawing.Size(100,40)
      $DropDownOLDLabel.Text = “Select Current Application:”
      $Form.Controls.Add($DropDownOLDLabel)

      $DropDownNEWLabel = new-object System.Windows.Forms.Label
      $DropDownNEWLabel.Location = new-object System.Drawing.Size(10,50)
      $DropDownNEWLabel.size = new-object System.Drawing.Size(100,40)
      $DropDownNEWLabel.Text = “Select New Application:”
      $Form.Controls.Add($DropDownNEWLabel)

      $Button = new-object System.Windows.Forms.Button
      $Button.Location = new-object System.Drawing.Size(120,80)
      $Button.Size = new-object System.Drawing.Size(100,20)
      $Button.Text = “Confirm Replace”
      $Button.Add_Click({Return-DropDown})
      $form.Controls.Add($Button)
      $form.ControlBox = $false

      $Form.Add_Shown({$Form.Activate()})
      [void] $Form.ShowDialog()

      return $script:choiceOLD
      return $script:choiceNEW
      }

      $Group = $null
      $Group = SelectApplication
      while ($Group -like “”){
      $Group = SelectApplication
      }

      $CurrentApp = $script:choiceOLD #Name of the Current application
      $NewApp = $script:choiceNEW #Name of the New application
      $SiteServer = “Site.Server” #Your site server name
      $SiteCode =”AB1″ #Your site code
      # Customizations

      #Get SMS_ApplicationLatest WMI object
      $Current = Get-WmiObject -Namespace “root\SMS\site_$($SiteCode)” -Class “SMS_ApplicationLatest” -ComputerName $SiteServer -Filter “LocalizedDisplayName=’$CurrentApp’ and IsExpired=’False’ ”
      $New = Get-WmiObject -Namespace “root\SMS\site_$($SiteCode)” -Class “SMS_ApplicationLatest” -ComputerName $SiteServer -Filter “LocalizedDisplayName=’$NewApp’ and IsExpired=’False’ ”

      Write-host “——————————————————” -ForegroundColor Gray
      Write-host “Current Application name: ” -fore gray -NoNewline; Write-Host $($Current.LocalizedDisplayName) -ForegroundColor Yellow
      Write-host “New Application name: ” -fore gray -NoNewline; Write-Host $($new.LocalizedDisplayName) -ForegroundColor Green
      Write-host “——————————————————” -ForegroundColor Gray

      #Get Application Model Names
      $CurrentAppModelName = $Current.ModelName
      $NewAppModelName = $New.ModelName

      #Get SMS_TaskSequenceAppReferencesInfo WMI Object
      $TaskSequencePackageIDs = (Get-WmiObject -Namespace “root\SMS\site_$($SiteCode)” -Class “SMS_TaskSequenceAppReferencesInfo” -ComputerName $SiteServer -Filter “RefAppModelName Like ‘$CurrentAppModelName'”).PackageID
      Foreach ($TaskSequencePackageId in $TaskSequencePackageIds){
      If ($TaskSequencePackageIds.length -cgt 1){

      # 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 “`r`r`r”
      Write-host ” Dependent TaskSequence is: ” -fore gray -NoNewline; Write-Host $TaskSquenceName -ForegroundColor Cyan
      write-host “`r`r`r”
      Write-host ” Step Name: ” -fore gray

      # 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
      $TaskSequenceXML = [xml]$TaskSequenceResult.ReturnValue

      # Amend variable for Install applications, only replace those applications that we need to
      $InstallApplicationVariableNodes = Select-Xml -Xml $TaskSequenceXML -XPath “//variable[contains(@name,’ApplicationName’)]”
      foreach ($InstallApplicationVariableNode in $InstallApplicationVariableNodes)
      {
      $InstallApplicationVariableNode.Node.’#text’ = $InstallApplicationVariableNode.Node.’#text’ -replace “$CurrentAppModelName,”, “$NewAppModelName,” -replace “,$CurrentAppModelName”, “,$NewAppModelName” -replace “$CurrentAppModelName”, “$NewAppModelName”
      }

      # Amend command line for Install other applications, only replace those applications that we need to
      $InstallApplicationCommandLineNodes = Select-Xml -Xml $TaskSequenceXML -XPath “//step[contains(@type,’SMS_TaskSequence_InstallApplicationAction’)]”
      foreach ($InstallApplicationCommandLineNode in $InstallApplicationCommandLineNodes)
      {
      if ($InstallApplicationCommandLineNode.Node.action -match $CurrentAppModelName) {
      $InstallApplicationCommandLineNode.Node.action = $InstallApplicationCommandLineNode.Node.action -replace “$CurrentAppModelName,”, “$NewAppModelName,” -replace “,$CurrentAppModelName”, “,$NewAppModelName” -replace “$CurrentAppModelName”, “$NewAppModelName”
      Write-Host ” $($InstallApplicationCommandLineNode.Node.name) ” -ForegroundColor Cyan -NoNewline; write-host “– ” -fore White -NoNewline; Write-Host $($Current.LocalizedDisplayName) -fore Yellow -NoNewline; Write-Host ” replaced with ” -fore gray -NoNewline; Write-Host $($New.LocalizedDisplayName) -fore Green
      }
      }

      #Replace 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 “`r`r`r”
      Write-Host ” Application ” -fore Gray -NoNewline; Write-Host $($New.LocalizedDisplayName) -fore Green -NoNewline; Write-Host ” has replaced ” -fore Gray -NoNewline; Write-Host $($Current.LocalizedDisplayName) -fore Yellow -NoNewline; Write-Host “, In Task Sequence ” -fore Gray -NoNewline; Write-Host $TaskSquenceName -fore Cyan
      write-host “`r`r`r”
      Write-Host ” Operation Succeded!” -ForegroundColor Green
      Write-host ” ——————” -ForegroundColor Green
      write-host “`r`r`r”

      }
      catch
      {
      Write-Host “Remove application $($Current.LocalizedDisplayName) and replace with $($New.LocalizedDisplayName) in task sequence $TaskSquenceName failed .Error message: $($_.Exception.Message)” -ForegroundColor red
      }
      }
      }
      If ($TaskSequencePackageIds.length -cgt 1){
      Write-host “——————————————————” -ForegroundColor Gray
      }

      If ($TaskSequencePackageIds -eq $null)
      {
      Write-host “——————————————————” -ForegroundColor Gray
      Write-host “There are No Dependant TaskSequences for — ” -fore gray -NoNewline; Write-Host $($Current.LocalizedDisplayName) -fore Yellow -NoNewline; Write-Host ” to be replaced in” -fore gray
      Write-host “——————————————————” -ForegroundColor Gray
      }
      Set-location $CurrentLocation

      Ta!

      • Zeng Yinghua
        Posted at 11:14 June 5, 2019
        Zeng Yinghua
        Reply
        Author

        Hello, thanks for posting this. Scripts format might goes wrong in comments, do you mind upload that to your github or OneDrive and share the link?

  • Leave a Reply

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