13 min read
Mastering Changelog Management with PowerShell
Changelogs keep your software updates clear and organized. Learn the best practices for creating and managing them in...
ScriptRunner Blog
In customer projects with System Center Configuration Manager, the challenge is to design task sequences flexibly. In essence, this means that an SCCM task sequence should be able to change.
This is illustrated in the following by a practical example. The respective task sequence should be used for approx. 350 applications, so that with each change (Application A in, Application B out, Application C out…) a corresponding manual effort was necessary. The process could be automated by making the changes with Powershell. A major customer in the banking sector realizes this with ScriptRunner.
For this purpose a task sequence template was created, which contains all steps that never or only very rarely change (task sequence variables, .NET installer, patches etc.). This template is copied from the script and the copy is filled with the complete new release data to be used. In this specific case, the release data is contained in a text file with all application parameters and already provided with the correct name from the SCCM Application Model.
To the script in detail
First load the ConfigMgr Powershell module:
Import modules ($Env:SMS_ADMIN_UI_PATH.Substring(0,$Env:SMS_ADMIN_UI_PATH.Length-5) + ‘ConfigurationManager.psd1’)
The following PowerShell function is used to copy the existing sequence, the template:
function duplicate_tasksequence ($origTSName,$newTSName) { try{ $ns_root = “ROOTSMSSite_$sitecode” $origTSPkg = GWMI -ComputerName $siteServer -Namespace $ns_root -Class “SMS_TaskSequencePackage” -Filter “Name=’$origTSName'”” “SMS_TaskSequencePackage”. # check if template exists if ($origTSPkg.PackageID -ne “”){ Write-Host “Template FOUND!” -ForegroundColor Green $methodTSPkgName = “SMS_TaskSequencePackage” $mc = [WMIClass]”$($ns_root):$($methodTSPkgName)” $inParamsGet = $mc.psbase.GetMethodParameters(“GetSequence”) $inParamsGet.TaskSequencePackage = $origTSPkg $outParamsGet = $mc.psbase.InvokeMethod(“GetSequence”,$inparamsGet,$null) $newTS = $outParamsGet.TaskSequence $newTSPkg = ([WMIClass]”$($ns_root):$($methodTSPkgName)”).CreateInstance() $newTSPkgID = $newTSPkg.PackageID $newTSPkg = $origTSPkg $newTSPkg.name = $newTSName $newTSPkg.PackageID = $newTSPkgID $inParamsSet = $mc.psbase.GetMethodParameters(“SetSequence”) -==- proudly presents $inParamsSet.TaskSequencePackage = $newTSPkg $outParamsSet = $mc.psbase.InvokeMethod(“SetSequence”,$inParamsSet,$null) $ntsPkg = GWMI -ComputerName $siteServer -Namespace $ns_root -Class “SMS_TaskSequencePackage” | where { $outParamsSet.SavedTaskSequencePackagePath.Contains($_.PackageID)} return $ntsPkg.PackageID } else{ return “” } } catch{ return $null; } }
Calling the function creates a new task sequence from the template:
$newSequence = duplicate_tasksequence "$TSTemplate" "$TargetTS"
Then the object of the new sequence is loaded for editing via Get-CMTaskSequenz:
$CMTS = Get-CMTaskSequence -Name $TargetTS
Note: All steps in the sequence must be added or returned as IResultObject.
The GetSequence method can now be used to edit the task sequence:
$Parameters = New-Object “System.Collections.Generic.Dictionary[string, object]” $Parameters.Add(“TaskSequencePackage”,$CMTS) $TSmethod =$CMTS.ConnectionManager.ExecuteMethod(“SMS_TaskSequencePackage”, “GetSequence”, $Parameters) $TaskSequence = $TSmethod.GetSingleItem(“TaskSequence”)
Now we have the sequence about the ConnectionManager-Property in a$TaskSequence variable, with which steps can be added.
We define the new step we want to add as “Install Application Action” via the Connection Manager that has already been used:
$newStep = $CMTS.ConnectionManager.CreateEmbeddedObjectInstance("SMS_TaskSequence_InstallApplicationAction")
foreach ($app in $Applications){ $appName= (Get-CMApplication -Name $app) $newStep.Name = “$app” $newStep.ApplicationName = $appName.ModelName if( $appName.LocalizedDisplayName -eq $null){ #Error Handling – If App is not available in SCCM Site -> EXIT Write-Host “NOT FOUND: $app — PLEASE ADD THE APPLICATION TO SCCM SITE $SiteCode” -ForegroundColor Red Exit }
$appName is the actual application that matches the name in the text file. The step “Install Application” is also given the name of the application.
Note: You have to be careful here, as the GUI can only assign 40 characters for a step name, but the Powershell script has no limit here. Longer names do not cause the sequence to stop working, but they cannot be edited later in the GUI.
To select the application we want to add to the step, we need the unique Application ID (ScopeID). This is located in the ModelName object.
Now the main part of the step has been described:
The step has more objects and options that are not used here for clarity.
A very interesting option is surely ContinueOnErrorWith
the line$newStep.ContinueOnError = “true” in SCCM the check mark at “Continue on Error” would be set. When used in the “For-Each” loop, however, this would apply to every step – which is somewhat unattractive or undesirable in productive sequences.
After many steps have been created, they are stored in a generated array and assigned to a task sequence group. In the example, this group is called APPLICATIONS.
To do this, the group is simply addressed with its sequential number (starting with 0, where 0 means no group):
$TaskSequenceSteps = $TaskSequence.GetArrayItems(“Steps”) $TaskSequenceSteps = $TaskSequence.GetArrayItems(“Steps”) $GroupSteps = $TaskSequenceSteps[1].GetArrayItems(“Steps”) $GroupSteps.Add($newStep); # Write array into sequence $TaskSequenceSteps[1].SetArrayItems(“Steps”, $GroupSteps); $TaskSequence.SetArrayItems(“Steps”, $taskSequenceSteps); }
So you select group 1 and add the steps from the array to that group.
Now the task sequence has to be saved or written back. This is done in the same way as “opening” the sequence:
$Parameters = New-Object “System.Collections.Generic.Dictionary[string, object]” $Parameters.Add(“TaskSequence”, $TaskSequence) $Parameters.Add(“TaskSequencePackage”, $CMTS) $TSmethod = $CMTS.ConnectionManager.ExecuteMethod(“SMS_TaskSequencePackage”,”SetSequence”, $Parameters)
The template before the script
The new sequence after the script
Extend ScriptRunner with ScriptRunner Connectors and integrate your monitoring, IT service management, ticket, rights management system, etc. to create fully automated control loops in your IT operations.
Jan 28, 2025 by Jeffery Hicks
Changelogs keep your software updates clear and organized. Learn the best practices for creating and managing them in...
Dec 19, 2024 by Jeffery Hicks
Boost IT efficiency with Winget and PowerShell! Learn how to automate app installations, updates, and management...
Dec 17, 2024 by Sonny Jamwal
Extend PowerShell with .NET for powerful event automation. Learn how to monitor and handle system events like a pro!...
Frank Kresse is Head of Product and CEO of ScriptRunner. As the inventor of the automation and delegation solution for PowerShell, he advises clients on use case scenarios and develops solutions for the automation and the digitalization of their processes. He is also involved in technology start-ups.