Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Configuration Manager does not automatically turn task-sequence variables into ordinary PowerShell variables. For a simple input, pass the value through the Run PowerShell Script step’s Parameters field, for example -ComputerName '%_SMSTSMachineName%'. When a script must read, create, or update task-sequence state, use the Microsoft.SMS.TSEnvironment COM object:

$tsenv = New-Object -ComObject Microsoft.SMS.TSEnvironment
$value = $tsenv.Value('DeployEnvironment')
$tsenv.Value('DeploymentResult') = 'Success'

The methods apply to PowerShell scripts running inside an active Microsoft Configuration Manager task sequence, including Windows PE and the full operating system phases.

Understand the four variable namespaces

A Configuration Manager task-sequence variable is state maintained by the task-sequence engine. It is not automatically a PowerShell variable, a Windows process environment variable, or a script parameter.

  • Built-in variables: Engine-created values such as _SMSTSLogPath and _SMSTSMachineName.
  • Action variables: Values that may exist only while a particular action is running; their lifetime is step-dependent.
  • Custom variables: Administrator- or script-created workflow values.
  • Collection and device variables: Values assigned in the Configuration Manager console.
  • Array variables: Structured data exposed as flattened names such as OSDPartitions0FileSystem.

Configuration Manager evaluates collection variables first, device-specific variables override collection values, and values set during the running task sequence take precedence over both. See Microsoft’s task-sequence variable documentation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Sale
PowerShell for Sysadmins: Workflow Automation Made Easy
  • Book - powershell for sysadmins: workflow automation made easy
  • Language: english
  • Binding: paperback

Choose the right method

Need Use
One or two explicit script inputs Script parameters with %VariableName% in the step’s Parameters field
Read or write several values Microsoft.SMS.TSEnvironment
Return one calculated result Output to task sequence variable
Set a fixed value Set Task Sequence Variable
Choose values from rules Set Dynamic Variables

Read a task-sequence variable inside PowerShell

Read a custom variable

$tsenv = New-Object -ComObject Microsoft.SMS.TSEnvironment
$deploymentType = $tsenv.Value('DeploymentType')
Write-Output "DeploymentType: $deploymentType"

Value() is the documented interface for retrieving a task-sequence variable. Do not expect $env:DeploymentType to contain the value; that syntax accesses the Windows process environment instead.

Read built-in values

$tsenv = New-Object -ComObject Microsoft.SMS.TSEnvironment
$logPath = $tsenv.Value('_SMSTSLogPath')
$machineName = $tsenv.Value('_SMSTSMachineName')

Write-Output "Machine: $machineName"
Write-Output "Task-sequence log path: $logPath"

Validate a required value

$tsenv = New-Object -ComObject Microsoft.SMS.TSEnvironment
$appChannel = $tsenv.Value('AppChannel')

if ([string]::IsNullOrWhiteSpace($appChannel)) {
    throw 'Required task-sequence variable AppChannel is missing or empty.'
}

Check that the spelling matches, that the producing step ran earlier, and that the variable is available in the current scope.

Pass a variable as a script parameter

  1. Create or populate the variable earlier in the sequence, for example with Add → General → Set Task Sequence Variable, using AppChannel as the name and Pilot as the value.
  2. Add Add → General → Run PowerShell Script.
  3. Use a parameterized script:
param(
    [Parameter(Mandatory)]
    [string]$Channel
)

Write-Output "Selected channel: $Channel"
  1. In the step’s Parameters field, enter:
-Channel '%AppChannel%'

Configuration Manager expands %AppChannel% before PowerShell receives the argument. In this field, use single quotation marks around values that may contain spaces or special characters; Microsoft warns that double quotation marks can be processed incorrectly in this step. See the Run PowerShell Script step documentation.

Inline script example

For an inline script, pass the value through Parameters rather than generating PowerShell source code:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
-SourcePath '%OSDTargetSystemDrive%Installers'
param([string]$SourcePath)

if (-not $SourcePath) {
    throw 'SourcePath was not supplied.'
}

Write-Output "Using source path: $SourcePath"

The Parameters field is for arguments consumed by your script. Do not put host options such as -NoLogo -ExecutionPolicy Unrestricted -File MyScript.ps1 there.

Set or update a variable for later steps

$tsenv = New-Object -ComObject Microsoft.SMS.TSEnvironment

$tsenv.Value('DeploymentResult') = 'Success'
$tsenv.Value('DeploymentTimestamp') = (Get-Date).ToString('s')

Assigning a nonexistent name creates it; assigning an existing name updates it. Subsequent steps can test DeploymentResult with a task-sequence condition such as Task Sequence Variable DeploymentResult equals “Success”. To delete a custom variable, assign an empty string:

$tsenv.Value('DeploymentResult') = ''

Underscore-prefixed variables are generally read-only. Read _SMSTSLogPath, but write a separate custom variable instead of attempting to replace it.

Capture one result with Output to task sequence variable

When a script has one simple result, configure the Run PowerShell Script step’s Output to task sequence variable setting. For example, use this script:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
(Get-Culture).TwoLetterISOLanguageName

Set the output variable name to CurrentOSLanguage. A later step can use the condition Task Sequence Variable CurrentOSLanguage equals “en”. Standard output becomes the stored value, so do not mix diagnostic text with the result:

# Good: emits only the value
(Get-Culture).TwoLetterISOLanguageName

Use TSEnvironment when you need multiple outputs or precise control over when values are written.

Import all variables (optional)

Microsoft documents this convenience pattern:

$tsenv = New-Object -ComObject Microsoft.SMS.TSEnvironment

$tsenv.GetVariables() | ForEach-Object {
    Set-Variable -Name $_ -Value $tsenv.Value($_)
}

A variable named DeploymentType can then be referenced as $DeploymentType. Explicit retrieval is usually safer: it makes dependencies auditable, avoids collisions with automatic PowerShell variables, and reduces accidental exposure of secrets. Names containing hyphens are also awkward as PowerShell identifiers, so access them through Value('Name-With-Hyphen').

Protect credentials and other secrets

  • Do not pass a password as -Password '%AdminPassword%' unless you have accepted the logging consequences.
  • Use a hidden task-sequence variable and retrieve it through TSEnvironment where possible.
  • Never write secrets to standard output or diagnostic logs.
  • Configuration Manager warns that expanded command-line values can appear in smsts.log. If command-line expansion is unavoidable, Microsoft documents OSDDoNotLogCommand=TRUE as a mitigation.

Hidden variables are concealed from specified console, log, and debugger surfaces; they are not encrypted or impossible for an executing script to read. Treat them as usable runtime secrets, not as a complete security boundary.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Windows PE, full Windows, and standalone testing

The COM-object method requires an active task-sequence context. It is intended for scripts launched by the task-sequence engine in Windows PE or the full operating system. The Setup Windows and ConfigMgr transition changes phases, but the task-sequence environment remains the documented source of variables. Scripts launched manually outside the engine will not have that COM object.

For a reusable script, make the parameter the primary interface and fall back to the task-sequence environment:

param(
    [string]$DeploymentType
)

if (-not $DeploymentType) {
    try {
        $tsenv = New-Object -ComObject Microsoft.SMS.TSEnvironment -ErrorAction Stop
        $DeploymentType = $tsenv.Value('DeploymentType')
    }
    catch {
        Write-Verbose 'Not running inside a Configuration Manager task sequence.'
    }
}

if (-not $DeploymentType) {
    throw 'DeploymentType was not supplied.'
}

Write-Output "Deployment type: $DeploymentType"

This distinguishes a script parameter from a task-sequence variable and from a normal Windows environment variable.

Variable limits, arrays, and lifetime

  • Names may contain letters, numbers, underscores, and hyphens, cannot contain embedded spaces, and are limited to 256 characters.
  • The task-sequence environment has an 8 KB total size limit; an individual value cannot exceed 4,000 characters.
  • Values can be case-sensitive depending on use; password values are case-sensitive.
  • Array data is exposed through flattened member names. For example:
$tsenv = New-Object -ComObject Microsoft.SMS.TSEnvironment
$filesystem = $tsenv.Value('OSDPartitions0FileSystem')
$size = $tsenv.Value('OSDPartitions0Size')

Do not assume every array is available as a native PowerShell array. If an action variable must survive beyond its step, copy it to a custom variable before the action ends:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
$tsenv.Value('SavedWorkingDirectory') = $tsenv.Value('WorkingDirectory')

Troubleshoot common failures

Symptom Likely cause and fix
Empty value The variable is misspelled, set later, out of scope, or overridden. Verify ordering, spelling, and precedence.
Literal %Var% The field does not support substitution, or the syntax was placed inside the script body. Use the Parameters field or TSEnvironment.
Script parameter rejected Host options were entered instead of arguments matching the script’s param() block.
Value works in one step only It may be an action variable whose lifetime ended. Copy it to a custom variable.
Secret appears in smsts.log The value was expanded into a command line. Prefer hidden variables and in-script retrieval.
COM creation fails The script is not running inside the expected active task-sequence context, or it was launched manually.
Output variable contains extra text Diagnostics were written to standard output. Emit only the intended value.
Runtime value differs from console value Device or runtime precedence has overridden the collection value.

Write a safe diagnostic log

$tsenv = New-Object -ComObject Microsoft.SMS.TSEnvironment
$logPath = $tsenv.Value('_SMSTSLogPath')
$logFile = Join-Path $logPath 'ReadTaskSequenceVariable.log'

"Timestamp: $(Get-Date -Format o)" |
    Out-File -FilePath $logFile -Append -Encoding default
"AppChannel: [$($tsenv.Value('AppChannel'))]" |
    Out-File -FilePath $logFile -Append -Encoding default

Never include passwords, tokens, or other secrets in this diagnostic output.

Bottom line

Use %VariableName% in the Run PowerShell Script step’s Parameters field for explicit, simple inputs. Use Microsoft.SMS.TSEnvironment when the script must inspect or change task-sequence state. Use output capture for one calculated value, validate required inputs, respect variable scope and ordering, and design secret handling around the fact that command-line expansion can expose values in task-sequence logs.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.