I’m trying to create a way to offline debug PowerShell scripts that are intended for workstation deployment Task Sequences in Microsoft Deployment Toolkit (MDT). The scripts use the task sequence environment variables that are retrieved using a ComObject, $tsenv. The ComObject is only available while a task sequence is running so I would like to create a fake object that works the same as the ComObject returned from the Task Sequence environment and fill it with values that I capture from a previously running task sequence. Then I could debug the scripts offline with the values that actually existed in the deployment environment. The values in the running task sequence are returned by name like this,
$script_var1 = $tsenv.Value("OSDISK")
$script_var2 = $tsenv.Value("APPLYGPOPACK")
$script_var3 = $tsenv.Value("ASSETTAG")
There are over 150 values. I was trying to build an array object that would work exactly the same way by outputting all the values from the running task sequence like this,
$tsenv.GetVariables() | Where-Object {$_ -NotLike "_SMSTSTaskSequence"} | % {Write-Output "`$tsenv += New-Object -TypeName psobject -Property @{Name=`"$_`"; Value=`"$($tsenv.Value($_))`"}" >> vars.txt}
This gives me all the values with the names and if I create an empty $tsenv array then include the contents of this vars.txt file, it nearly works. I can see all the values in the $tsenv object, but I can’t access them by Name as I can with the ComObject. I’ve tried all the different ways I could think of, hashtable, array, dictionary, etc., but nothing get’s me as close as this and it still isn’t quite there. Anyone have a better way of doing this or a way to get to what I want?
First, if you want to export objects to be imported later I highly recommend the Export-CliXml
cmdlet. It will retain things like nested arrays and what not, so if "APPLYGPOPACK" returns an array of strings of what GPOs to apply, it will keep it as an array of strings when you import it later. What I would do here is make an empty hashtable, add all of your variables to it, and export as xml it for later reference.
$tsenvHT = @{}
$tsenv.GetVariables() | Where-Object {$_ -NotLike "_SMSTSTaskSequence"} | % {$tsenvHT.Add($_,$tsenv.Value($_))}
$tsenvHT | Export-Clixml .\vars.xml
Then you just use Import-CliXml
to restore that data later when you want to test. I'm going to convert it to a [PSCustomObject]
to work well with the next step.
$tsenv = [pscustomobject](Import-Clixml .\vars.xml)
Next, to reference things like you do with your $tsenv.value()
method, you can create a custom object and give it a .Value()
method to emulate what your ComObject is doing.
$tsenv | Add-Member -MemberType ScriptMethod -Value {param($VariableName);$This.$VariableName} -Name 'Value'
Then you can call it just like the ComObject to get your variable values:
$tsenv.Value("OSDISK")