Roberts Blog

The House of SCCM and Intune on System Center Street

Tag: Task Sequence

ConfigMgr Build 1910– Run Command Line–Output to task sequence variable

ConfigMgr Build 1910 released with a wholesome load of features, one in particular I’ll cover here, the addition of Output to task sequence variable in the existing task sequence Run Command Line and Run PowerShell steps.

This is a really handy feature.

I’ve been achieving the same result in a clunky manner for a while now. Execute something client-side during the task sequence, store the (cleaned up) output in a task sequence variable, do something with that variable further into the task sequence. Good example would be evaluating a registry key value. Not so easy pre-Build 1910.

If I wanted specific output that I can manipulate within the task sequence I’d write a bespoke script to get at it first, then I’d add to the tail end of the script some code to inject the output into a task sequence variable, then yield back to the task sequence engine.

Back in the ‘day you’d do it this way using either atypical scripting channels PowerShell or retro VBScript.


set env = CreateObject("Microsoft.SMS.TSEnvironment")
env("HelloWorld") = "SomeValue"


$tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment
$tsenv.Value("HelloWorld") = “SomeValue”

The drawback with this approach is that every script needs modification to clean up the output a little if needed, and then to store it away in a task sequence variable before returning back to the task sequence engine.

There is a way to overcome this with a reusable bare-bones wrapper\launcher script that does a couple of things, launches what you want to launch, be it a script or executable, and then stores the result in a task sequence variable and yields back.

On the whole this latter approach opens up the door to reuse of existing scripts et al without having to resort to making changes to them, you just wrap them and handle their output. It is still very clunky though, not ideal, all we want to do is bring back some output and look and do something with it.

We can now dispense with one layer of that solution, bringing the value back in a task sequence variable automatically, which means most of that script-bridging that I talk of above can be done away with. Great.

We can still run custom scripts or command lines to tailor output in-situ (filter it down), or resort to executing a script or process and returning its output in full. Returned in full the output will be trimmed to the 1,000th character.

What we do not need to do is run a few lines of script each time so as to gain access to the task sequence engines variables to store something away. That’s the difference here. Which turns out to be very enabling.

Worth noting that if we tailor the output in-script we can return a single value to do comparisons against further into the task sequence, nice and tidy, or return all the output, assuming whatever you want to find is within the first 1,000 characters, and use comparisons operators such as like to tease out what it is we’re looking for.

Here’s the Run PowerShell and Run Command Line steps with the Output to task sequence variable addition:

Once we have a value stored away we can evaluate it using the built-in task sequence engine logic, such as via a task sequence step’s Conditions:


That’s an explicit or absolute comparison (equals), which would mean that the output has to be something you can do a direct comparison against, whatever is outputting has to output a predictable singular value or predictable sentence as a result of the operation or via filtering.

If the output is unprocessed\unfiltered its no hassle, we can just as easily perform a wildcard match on the variables value, using the like operator for the condition:

There’s more that we can do, if we turn to the Set Dynamic Variable we can transform the existing value or spawn a new variable based on some complex-enough conditional checks, such as if variable is or is like X then set this or another variable to Y as an example:

So to summarise, if whatever you are executing returns a string of predictable characters, a single value, a sentence, you are good to go, just launch it and steer the output into a task sequence variable using this feature, evaluate it later on.

However, if you need to do some string manipulation you can do it using piping, filtering and the FOR commands /F switch within the CMD shell, or do it slightly differently with PowerShell. I’ll go at this within the CMD shell and use the Run Command Line step.

Let’s take SC QUERY as an example, here’s the output when pointed at a specific service:

TYPE               : 30  WIN32
        STATE              : 4  RUNNING
WIN32_EXIT_CODE    : 0  (0x0)
CHECKPOINT         : 0x0
WAIT_HINT          : 0x0

We want to know if this service is running, its state.

There’s two options here, run SC QUERY WINMGMT, return all its output and then use the like operator to see if Running is present, or, we can filter the output and return the state whether it is running, paused or stopped.

I’ve got a couple of examples for the Run Command Line step that use that classic FOR /F command and switch along with FIND /I  to pick at specific elements in the output, these stand as examples that you can modify and cast out from.

Bring back the STATE of a specific Windows service:

FOR /F "tokens=1,2,3,* delims= " %A in ('sc query Winmgmt ^| Find /I "state"') do @echo %D


SC Query Winmgmt | FOR /F "tokens=1,2,3,* delims= " %A in ('Find /I "state"') do @echo %D

Either of these approaches will bring back the state value of a specific service cleanly.

Retrieve a specific Registry value:

FOR /f "tokens=1,2,* delims= " %A in ('reg.exe query HKLM\Software\7-zip /v Path') do echo %C

The 7-zip Path value will be returned as-is.

Check if the device is Azure AD joined:

FOR /F "tokens=1,* delims=: " %A in ('dsregcmd /status ^| Find /I "AzureAdJoined"') do @echo %B

It’ll return a YES or a NO to evaluate later on.

Check if a process running:

FOR /F "tokens=1,* delims= " %A in ('tasklist /NH /FI "ImageName eq notepad.exe"') do @echo %A

This will bring back the processes name if it is running, a like or equal comparison on notepad.exe or notepad will flag it up as running, and an action can be taken in the task sequence.

I think I’ll leave this here, as you can see this is a very enabling feature that could easily be underestimated or undervalued in amongst all the other bolder and brassier features that Build 1910 is laden with.

I tweeted about this feature recently, put out a few interesting but clumsy examples. Would be interesting to see some examples of how you use this new feature, feel free to tweet them there or leave in the comments here:

ConfigMgr Build 1710 –Run Task Sequence (Preview Feature)

In ConfigMgr Build 1710, the Run Task Sequence step feature has entered pre-release.

Pre-release as a ‘term’ needs some definition.

Pre-release means a feature is fit for production use and has been well tested by Microsoft, has Microsoft Support fully behind it, but its a feature that is still being fleshed out, has a low customer uptake and thus a narrow telemetry surface.

If things go wrong with a Pre-release feature, the Product Group are all over it like a rash when prompted, so as to get things working and the feature made even more stable, but as the features stand, they are actually, even though the term Pre-release hints at non-production, production ready features.

Pre-release means production ready. So enabling the ability to use Pre-release features on your Site server does not invoke beta code or put the other features in peril, that’s what Technical Preview is for, code that hasn’t been ironed out fully yet and rated production ready.

Before a feature hits Pre-release you can kick the tyres in the Technical Previews in a non-production Hierarchy, and then plan to switch that feature on for the production Hierarchy when the feature arrives in Current Branch as Pre-release, or wait a while longer for it to move out of Pre-release.

Most of us will only switch on Pre-release for a Hierarchy if we’re going to use some of the features, makes perfect sense, it is a Hierarchy Setting:


Now, not all of you have, but all of you should have, a test lab running Current Branch, since it is a perfect place to switch on Pre-release and catch up on and review for production usefulness features as they drop into the Current Branch code base, for those that are running Technical Preview, many of these features will already be familiar.

The idea for Run Task Sequence seems to have originated with a UserVoice item being raised by Jerry and signed off as completed by David James (Djam) in the Product Group:


The circle of community\customer and Product Group\Microsoft is there for all to see, suggest a good idea, and if it gets enough votes it becomes production code.

Participation is not like trying to win a national lottery, UserVoice certainly is not based on luck of the draw, votes and product group interest make suggesting ideas and getting a success a real possibility for everyone. I suggest if you have a good idea to put it on UserVoice here.

I can see Run Task Sequence being quite a handy feature in the OSD space, but should forewarn everyone, don’t go chaining task sequences together for the sake of it, have a real use-case rather than just carving things out because you can, adding complexity can cripple, keep it simple.

From the documentation we get these key points to digest:

  • The parent and child task sequences are effectively combined into a single policy that the client runs
  • The environment is global. For example, if a variable is set by the parent task sequence and then changed by the child task sequence, the variable remains changed moving forward. Similarly, if the child task sequence creates a new variable, the variable is available for the remaining steps in the parent task sequence
  • Status messages are sent per normal for a single task sequence operation
  • The task sequences write entries to the smsts.log file, with new log entries that make it clear when a child task sequence starts

Chaining task sequences together requires a new step deposited in General called Run Task Sequence, as shown below:


I have a Task Sequence called Parent (Main) which is going to be a root Task Sequence, and below I’ve told it to chain to Child (No1) Task Sequence:


I’ve told the Child No1 Task Sequence to chain to Child No2


Here’s a list of what I built:

Task Sequence Name
Parent (Main) – Links to Child (No1)
Child (No1) – Links to Child (No2)
Child No2 – Is linked too but links to nothing

I deleted Child No1, and when opening Parent (Main) to edit, I received this prompt:


And get the usual un-configured step notification for the Run Task Sequence step that we’re use too when content is removed in a Task Sequence:


There doesn’t seem to be an easy way to view the topology of chaining that’s taking place in Task Sequences, I figure a community tool could do this easily, visualise the relationships, in the meantime Microsoft will iterate this feature and flesh it out a bit more I hope, a new tab in the properties for a Task Sequence so we can see its relationships without having to pour over the Steps to find where it makes the call, or an easy list to access showing all relationships.

Be great to hear how you are carving up Task Sequences using this new feature, what do you split on …

Powered by WordPress & Theme by Anders Norén