AutoPilot
Really Windows Autopilot is the future. As soon as the OEM’s get their act together, and offer machines without the bloatware and adware. Yea, I’m talking about you Anti-Virus Trial! Go away, shoo! Shoo! Give me Signature Images, or I’ll do it myself.
Unfortunately, I’m currently working for a client that is “Cloud Adverse”, and very… particular about Security. “have our machines go through the internet, and download our apps from a cloud, oh heavens no!!”.
So all machines come from the OEM’s and into a centralized distribution center, where they run a hodge-podge of OS Imaging tools to get the machines ready to ship out to each user.
And, No they don’t use any MDT… at least not yet…
Really it’s the Anti AutoPilot…
Where to start.
Well, when the machines arrive from the OEM, they are unboxed and placed on a configuration rack. If they are Desktop Machines, they are also connected to a KVM switch (Imagine several 8-port switches daisy chained together). Then they are plugged into power, network, and turned on.
Here’s our first challenge: How do we stop the PC from booting into the OEM’s OOBE process into OUR process? Well right now the technicians need to press the magic function key press at just the right time during boot up.
You know the drill, Press F12 for Dell, or perhaps press F9 for HP, or Press enter for Lenovo. Perhaps you have a Surface Device, and need to hold down the Volume button while starting the machine. Yuck, but better than nothing…
Well, the feedback we got from the technicians is that sometimes they miss pressing the button… at “just” the right time. This is really a problem for a Desktop PC’s connected to that KVM switch. If the Monitor doesn’t sync to the new PC quickly enough, you might easily miss pressing the boot override switch.
This sounded like a good challenge to start with.
Audit Mode
Really, IT departments don’t use Audit Mode. Audit Mode is a way to make customizations *during* Windows Setup and then re-seal the OS, so the end-user gets the nice shiny Windows Setup process (Specialize and OOBE) that they expect in a new PC.
Deployments in IT are all about bypassing the shiny Windows OOBE experience. No we don’t care about all the fancy new features in Cortana, We have already signed the SA agreement with Microsoft, we already know the domain to connect to, and our company has only one locale and keyboard type. IT departments would much rather skip all that, and get the user to their machine. So the thought of re-sealing a machine and going *back* to OOBE when we just finished joining to the domain and installing apps is silly.
But there are some Possibilities here. Turns out, that when Windows Setup is running, it will look for an Unattend.xml file and try to use it.
Methods for running Windows Setup
MDT uses an Unattend.xml file on the local machine it we can skip over the settings we know about, and re-launch MDT LiteTouch when finished. What about this process? If we place the Unattend.xml file on the root of a removable USB drive, the Windows version on the hard disk will look there and use these settings. The Lab Techs appeared to have a lot of USB sticks laying around, so using them shouldn’t be a problem.
We can’t use a MDT unattend.xml file as-is, but we can use AuditMode to get to a command prompt and install our own MDT LitetouchPE_x64.wim file.
- Boot into Audit Mode.
- While in Audit Mode, auto login using the Administrator Account.
- Find our PowerShell script and run it!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<unattend xmlns="urn:schemas-microsoft-com:unattend"> | |
<settings pass="oobeSystem"> | |
<component name="Microsoft-Windows-Deployment" 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"> | |
<Reseal> | |
<Mode>Audit</Mode> | |
</Reseal> | |
</component> | |
</settings> | |
<settings pass="auditSystem"> | |
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="wow64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | |
<AutoLogon> | |
<Enabled>true</Enabled> | |
<LogonCount>5</LogonCount> | |
<Username>administrator</Username> | |
</AutoLogon> | |
</component> | |
</settings> | |
<settings pass="auditUser"> | |
<component name="Microsoft-Windows-Deployment" 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"> | |
<RunSynchronous> | |
<RunSynchronousCommand wcm:action="add"> | |
<Description>Run script</Description> | |
<Order>1</Order> | |
<!– Enumerate through all drives looking for the MYIT_OEMBypass.ps1 script, if found, run it. Leave the command prompt open. –> | |
<Path>cmd /c "(FOR %i IN (C D E F G H I J K L N M) DO IF EXIST %i:\MYIT_OEMBypass.ps1 Powershell -executionpolicy ByPass %i:\MYIT_OEMBypass.ps1) & pause"</Path> | |
<WillReboot>OnRequest</WillReboot> | |
</RunSynchronousCommand> | |
</RunSynchronous> | |
</component> | |
</settings> | |
</unattend> |
PowerShell script
Once we are in PowerShell, we now have full access to the system, and can modify it in any we choose. In this case, I have copied a LiteTouchPE_x64.wim file to the USB Stick, and we can force the Hard Drive to boot from that instead, continuing our process in MDT LiteTouch. Yea!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
Bypass file for OEM OOBE Setup. | |
Called from within Audit Mode. | |
#> | |
param( | |
[int] $TargetDisk = 0, | |
[string] $NewBootWim = "$PSScriptRoot\Generic_x64.wim", | |
[string] $UserName = 'MDTServer\MDTNonInteractive', | |
[string] $Password = 'UnSecurePassword1234', | |
[string] $BootType = 'x64', | |
[string] $Target = 'h:' | |
) | |
$ErrorActionPreference = 'stop' | |
#region Find the largest on-disk partition | |
############################################################################### | |
$TargetDrive = get-disk –Number $TargetDisk | | |
Get-partition | | |
Sort –Descending –Property Size | | |
Select-Object –First 1 | | |
Get-Volume | | |
foreach-object { $_.DriveLetter + ':' } | |
# get a drive letter for the system partition | |
get-disk –Number $TargetDisk | | |
get-partition | | |
where-object { -not $_.DriveLetter } | | |
Where-Object Type -eq System | | |
Add-PartitionAccessPath –AccessPath $Target | |
#endregion | |
#region Connect to a network share if Source is over the network… | |
############################################################################### | |
if ( -not ( test-path $NewBootWim ) ) { | |
if ( $newBootWim.StartsWith('\\') -and $UserName -and $Password ) { | |
# COnnect to the network share. | |
net use "$(split-path $NewBootWim)" /user:$UserName "$Password" | |
} | |
} | |
#endregion | |
#region Copy the Boot WIM | |
############################################################################### | |
new-item –ItemType directory –path $TargetDrive\Sources –Force –ErrorAction SilentlyContinue | Out-Null | |
copy-item $NewBootWim $TargetDrive\Sources\Boot.wim | |
robocopy /e $PSScriptRoot\x64 $Target\ /xf bcd bcd.log | |
#endregion | |
#region Create a BCD entry | |
############################################################################### | |
Bcdedit /create "{ramdiskoptions}" /d "Ramdisk options" | |
Bcdedit /set "{ramdiskoptions}" ramdisksdidevice boot | |
Bcdedit /set "{ramdiskoptions}" ramdisksdipath \boot\boot.sdi | |
$Output = bcdedit –create /d "MYIT_OEMHack" /application OSLOADER | |
$GUID = $output | %{ $_.split(' ')[2] } | |
bcdedit /set $Guid device "ramdisk=[$TargetDrive]\sources\boot.wim,{ramdiskoptions}" | |
bcdedit /set $Guid osdevice "ramdisk=[$TargetDrive]\sources\boot.wim,{ramdiskoptions}" | |
bcdedit /set $Guid path \windows\system32\boot\winload.efi | |
bcdedit /set $Guid systemroot \windows | |
bcdedit /set $Guid detecthal yes | |
bcdedit /set $Guid winpe yes | |
bcdedit /set $Guid ems no | |
bcdedit /set $Guid isolatedcontext yes | |
Bcdedit /displayorder $Guid –addfirst | |
Bcdedit /default $Guid | |
Bcdedit /timeout 10 | |
#endregion | |
#region Reboot | |
############################################################################### | |
write-host "DONE" | |
shutdown –r -f –t 0 | |
#endregion |
Now we have a bridge between the OEM system and our LiteTouch, or any other automated WinPE disk.
Yea! Now for the *REAL* automation to begin… 🙂
-k