Summary: Use Windows PowerShell to inject drivers and populate the data for Unattend.xml.
Hey, Scripting Guy! I have a Windows To Go key. Is there a script to automatically give the key a proper workstation name or possibly even add some additional drivers?
—TG
Hello TG,
Honorary Scripting Guy, Sean Kearney, is here, and the magical answer to your question, which is, "YES!"
Note This is the fourth post in a five-part series. Before you read this, you should read:
- Use PowerShell to Create Windows To Go Keys—Part 1
- Use PowerShell to Create Windows To Go Keys—Part 2
- Use PowerShell to Create Windows To Go Keys—Part 3
Windows To Go isn’t really all that special. The ability to add drivers though DISM, automatically name a workstation, or join a workstation to a domain through Unattend.xml is still there.
The question is, "What drivers need to be injected into a Windows To Go key?"
First consider what are your target hardware platforms? If you have a defined set of machines, you could prepopulate the set after downloading them from the vendor.
Your other option is to consider that there is really only a small set of network card vendors and video drivers. If you were to prepopulate at least the main drivers from Intel, NVIDIA, and ATI for Video, and then possibly a few key network card drivers, the Windows To Go environment should be “mostly there” for a number of platforms.
To add drivers to the Windows To Go key, I use the Add-WindowsDriver cmdlet. It’s very much like using DISM. I need to provide the folder that contains the drivers I am adding and the drive letter of the operating system on the Windows To Go key.
For this example, I am continuing with the presumption that you are using the variables from my previous post and that the drivers are contained within the same folder as our PowerShell script in a folder called Drivers.
$Drivers=’.\Drivers’
Add-WindowsDriver –Path “$DriveOS`:” –driver $Drivers –recurse
These lines will inject all drivers found within the Drivers folder into the Windows To Go key. If you remove the –recurse parameter, it will only target the root of the $Drivers variable.
To populate the settings needed for the workstation, I need to create an Unattend.xml file and copy it directly into the Sysprep folder within the Windows To Go key. At bootup, the Windows operating system will process this file and its commands for configuration.
This will be similar to working with the SAN-Policy.xml file with the exception that the data will be forever changing. Some values, such as the workstation name, will need to be populated.
I can also use a here string for this case because it allows me to dynamically create the file.
A simple Unattend.xml file to assign the time zone, workstation name, and various details in Windows could look the following example. It will create a workstation named WTG- followed by a random number sequence, and then set the time zone as Eastern Standard Time.
$Computername=”WTG-$(Get-Random)”
$Organization=’Contoso Inc.’
$Owner=’Contoso Inc. IT Dept.’
$Timezone=’Eastern Standard Time’
$AdminPassword=’P@ssw0rd’
$Unattend=@"
<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">
<settings pass="specialize">
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ComputerName>$Computername</ComputerName>
<RegisteredOrganization>$Organization</RegisteredOrganization>
<RegisteredOwner>$Owner</RegisteredOwner>
<TimeZone>$Timezone</TimeZone>
</component>
</settings>
<settings pass="oobeSystem">
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<UserAccounts>
<AdministratorPassword>
<Value>$Adminpassword</Value>
<PlainText>true</PlainText>
</AdministratorPassword>
</UserAccounts>
<AutoLogon>
<Password>
<Value>$Adminpassword</Value>
<PlainText>true</PlainText>
</Password>
<Username>administrator</Username>
<LogonCount>1</Log\onCount>
<Enabled>true</Enabled>
</AutoLogon>
<RegisteredOrganization>$Organization</RegisteredOrganization>
<RegisteredOwner>$Owner</RegisteredOwner>
<OOBE>
<HideEULAPage>true</HideEULAPage>
<SkipMachineOOBE>true</SkipMachineOOBE>
</OOBE>
</component>
</settings>
<cpi:offlineImage cpi:source="" xmlns:cpi="urn:schemas-microsoft-com:cpi" />
</unattend>
"@
I can use the same process as I did with the SAN-Policy.xml file to re-create this file dynamically, but at the end, I will copy the file directly to the Sysprep folder on the Windows To Go key.
$UnattendFile=’.\unattend.xml’
Remove-item $UnattendFile -erroraction SilentlyContinue
Add-content -path $Unattendfile -Value $Unattend
Copy-Item -path $Unattendfile -destination "$DriveOS`:\Windows\System32\Sysprep"
With this is place, I can customize the individual Windows To Go keys with the data needed for the operating system. Of course, this is only an example for the Unattend.xml file, and there are better ways to obfuscate the Administrator password or to have the computer join a domain afterwards (whether online or offline).
What more can we do? Here’s a fun thought. Maybe we can wrap this whole script together as a workflow to image multiple keys at once!
...and that is a task I shall explore tomorrow.
I invite you to follow The Scripting Guys on Twitter and Facebook. If you have any questions, send an email to The Scripting Guys at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, remember to eat your cmdlets every day with a dash of creativity.
Sean Kearney, Windows PowerShell MVP and Honorary Scripting Guy