About a week ago, I started a new job as a sysadmin for a local business. In an effort to relieve some time-pressure from my partner (we are a two-man tech team), I spun up an MDT server to help streamline PC builds. The systems needing to be out the door soonest were going to be kiosk machines, and as part of that, I needed the MDT task sequence to create a local user account, and set that user to automatically log in.
Simple, right? Well as it turns out, not exactly.
Enabling a user account to automatically log on is a trivial task. Create the account, then set some registry values. It wasn’t long before I had a PowerShell script that did all this automatically. And running a PowerShell script in an MDT task sequence is also pretty straight-forward.
But it didn’t work. As soon as the computer restarted, the registry values (namely DefaultUserName and AutoAdminLogon) were missing.
As it turns out, MDT uses those same registry values to automatically log on as Administrator, when the image is finished copying to disk and the new operating system starts up for the first time. One of the last things it does is remove those values, so after deployment, logging on as Administrator (or any new account) requires a password.
I thought at first that it would be good enough to create a scheduled task, that would download the scripts from the deployment share and execute them later, after the deployment had finished (I set the task trigger as t+5 minutes to give it a chance to wrap up). Sadly, this did not work. I had trouble copying the scripts after deployment, even with share credentials hard-coded or the share set to Everyone permissions.
I suspect this is because if you miss the “do you want your pc to be discoverable” prompt when the operating system first boots and makes its initial connection to the network, the network profile (or category) is set to Public. When the profile is Public, by default, Network Discovery is disabled, and file shares that are not mapped as a drive will be inaccessible (MDT actually mounts the deployment share as the Z: volume during the deployment process, which means, among other things, that its contents are accessible regardless of network category).
To get around this, I had my scheduled-task script just write the enable-autoLogon script to disk using a Here-String piped to Out-File. It’s important to note that the here-string must be formatted as @’ to make it literal, and not expandable with @” as the latter won’t print the $variables to your output file, and hilarity will ensue.
But still, the end result was the same – when the computer rebooted, the AutoAdminLogin registry value was defaulted back to “0.”
Thinking it had to be the ZTICleanup.wsf script doing the resetting, I began my scheduled-task script with a while loop, so that it would wait until the wscript process terminated before adding the registry values. No wscript process, and the task sequence windows are gone, the Z: drive is unmapped, etc. – the deployment is 100% finished. If the wscript process was running, the script would just sleep for 10 seconds and then check again, until the process was gone.
Still no dice, though. The registry values would not persist.
So MDT must do something in between exiting the deployment process and the next reboot. Maybe it’s a shutdown or logoff script, I’m not entirely sure.
So, this whole “simple task” ultimately resulted in a process like this:
- In the MDT task sequence, a PowerShell script is run that does two things: First, it writes two other scripts to local storage: a PowerShell script, and a batch script that just calls the PowerShell script. Second, it creates a new scheduled task, to be triggered at the next startup, which executes the batch script (I had problems with the newly-created scheduled task running the PowerShell script directly, so the task calls the batch script instead).
- When the PC is rebooted after deployment, the scheduled task runs on startup. The new batch script executes the new PowerShell script. From there, the local user is created, the autologon registry values are set, and the currently-running scheduled task is disabled (so it doesn’t cause an infinitely-repeating ‘reboot on next startup’ loop). Lastly, the computer reboots – and when it comes back up, it logs right in to Windows as the kiosk user.
Once this was in place, the kiosk PC setups became ~75% automated, which will immediately save my partner valuable time with each deployment. And with time and testing, I’m sure we can take that ~75% to ~95%.
More complicated fun than expected? Definitely yes. But it all makes sense after having worked through it, and explored every wrong path to the eventual fix.
Lucky for you, at least if you’re here because you’re in the Google-everything phase of trying to set up some kiosks with MDT, all you need to do is modify and execute this PowerShell script in your task sequence.
Go be the hero 🙂