Thanks to Johan Arwidmark and Dan Vega for pointing me out to this bug. It took me a while to set up a scenario where it could reproduce, but it’s a good bug. Windows 10 In-Place Upgrade is an important new feature of Windows 10, and it’s good to have MDT support it.
When upgrading to Windows 10 Version 1709 using the built-in MDT “Standard Client Upgrade Task Sequence”, you will get an error during OS upgrade within a MDT Wizard page that shows something like:
A VBScript Runtime Error has occurred: Error: 500 = Variable is undefined VBScript Code: ------------------- IsThereAtLeastOneApplicationPresent
At this point, the OS *has* been upgraded, but the Task Sequence can no longer continue.
During OS upgrades, MDT needs a way to hook into the OS Installation process when done and continue installation tasks in the New OS.
Before In-Place upgrades, MDT would perform this by adding in a custom step into the unattend.xml file. Perhaps you have seen this segment of code before:
<FirstLogonCommands> <SynchronousCommand wcm:action="add"> <CommandLine>wscript.exe %SystemDrive%\LTIBootstrap.vbs</CommandLine> <Description>Lite Touch new OS</Description> <Order>1</Order> </SynchronousCommand> </FirstLogonCommands>
Windows would run the LTIBootStrap.vbs script, which would call the LiteTouch.wsf script, which would find the existing Task Sequence environment and kick of the remaining steps within the “State Restore” of the Task Sequence.
For the Windows 10 In-Place upgrade process, instead of processing the unattend.xml file, they have their own method of calling back into our LiteTouch environment using a SetupComplete.cmd file. This SetupComplete.cmd is responsible for finding our LiteTouch script and calling it.
It took me a while to setup a repro scenario (my test lab is configured for new-computer scenarios with the Windows 10 Eval bits, which can’t be used in an In-Place upgrade scenario). But I was able to reproduce the issue, and I got the bug, and was able to get the bdd.log file for analysis.
The challenge here is that during In-Place upgrade, I can’t open a Cmd.exe window for debugging using F8 or Shift-F10. Instead I hard coded a “start cmd.exe” line into the SetupComplete.cmd file.
What I observed is that the Window being displayed was the ZTIGather.wsf progress screen. LiteTouch.wsf will kick off the ZTIGather.wsf script early in the process, and will show a customized version of the LiteTouch wizard as a progress dialog. Well clearly the wizard isn’t working properly. But after closer analysis, ZTIGather.wsf shouldn’t be running AT ALL. For some reason, LiteTouch.wsf didn’t recall that it was in the MIDDLE of a task sequence, and that it should just directly go back to the TS in progress.
MDT has two methods for storing variables. When within the SMS Stand Alone Task Sequencing Engine, MDT LiteTouch scripts will read the SMS variables through the Microsoft.SMS.TSEnvironment COM object. But if ZTIUtility.vbs can’t open the variable store, it will store variables locally in the Variables.dat file.
Finally, after getting a powershell.exe window, creating the Microsoft.SMS.TSEnvironment, and making a couple of test calls to verify the contents of the variable store, a surprise. All variables returned empty *Successfully* (which is bad) but writes caused an Exception (which is correct). Since we were not running the SMS Stand Alone Task Sequencing Engine, all calls should have caused an exception.
Why is the Microsoft.SMS.TSEnvironment COM object registered, but not working? Well, that’s still under investigation, but now we can work on a fix/work around for MDT!!!
The fix (Not written by me), is to force the Microsoft.SMS.TSEnvironment COM object to unregister before calling LiteTouch.wsf. This can be done by a simple call at the start of the SetupComplete.cmd script:
:: Workaround for incorrectly-registered TS environment reg delete HKCR\Microsoft.SMS.TSEnvironment /f
The issue has been acknoleged by Microsoft, and this fix is currently targeted for the next release of MDT.