I received at work a Surface Pro 2 and Windows To Go certified USB sticks. Because of the UEFI requirements and the fact that Surface devices don’t have a built-in ethernet adapter, I changed my mind about how to industrialise the installation of such devices.

As my administrative distribution point is portable and I decided to move it to the USB stick and perform the installation directly from the USB stick without any network.

On the USB distribution point, I’ve got the extracted ISO of Windows 8.1 (Enterprise edition in my case), a custom answer file,… and drivers:

As long with these drivers there are some interesting PDF files to download and at the end of document, one can read:



Good idea 🙂

I wanted to keep it simple and started writing a post-installation script exclusively in PowerShell that first deploys drivers.

Here’s how my post-installation script starts:

#region drivers $letter = (Get-Disk | ? BusType -eq "USB" | Get-Partition)[0].DriveLetter Write-Verbose -Message "Starting to install drivers" -Verbose (Get-ChildItem -Path "$($letter):\DISTRIB\WIN81\DRIVERS_x64" -Directory | Sort LastwriteTime -Descending:$false | select -Last 1 ).FullName | ForEach-Object { Get-ChildItem -Path $_ -Recurse -Filter *.inf -Exclude autorun.inf | ForEach-Object -Process { '{0}' -f $_.FullName & (Get-Command "$($env:SystemRoot)\system32\pnputil.exe") @('/i','/a',"$($_.FullName)") } } #endregion drivers

After loading the wireless driver, I could start configuring the wireless interface and once on the network I’ll perform the remaining tasks that require network availability: activation, updating,…

Getting on the network is a crucial task. If it fails, all the remaining tasks would also fail.

I wanted to have also an elegant way of detecting when my wireless interface was fully configured and ready to perform online tasks.

I couldn’t use the following old trick as it isn’t robust and it is sequential.

Test-Connection -ComputerName ::1 -Count 10

I chose the .Net eventing path. Here’s how:

#region wireless $network = New-Object System.Net.NetworkInformation.NetworkChange Register-ObjectEvent -InputObject $network -EventName NetworkAvailabilityChanged -Action { (New-Event -SourceIdentifier "NetworkAvailabilityChanged" -Sender $args[0] –EventArguments $args[1].SourceEventArgs.NewEvent.TargetInstance) } # Perform some certificate related tasks <# ... #> # Start some services Get-Service -Name dot3svc | Set-Service -StartupType Automatic Get-Service -Name eaphost,ndisuio | Start-Service -ErrorAction SilentlyContinue Start-Service -Name dot3svc # Import the wireless profile & (Get-Command "$($env:SystemRoot)\system32

etsh.exe") @("wlan","add","profile","filename=$($letter):\Wi-Fi-Intranet.xml","interface=Wi-Fi","user=all") Wait-Event -SourceIdentifier NetworkAvailabilityChanged Get-Event -SourceIdentifier NetworkAvailabilityChanged | Remove-Event #endregion wireless

Bonus: the .Net Class [System.Net.NetworkInformation.NetworkChange] handles two kind of events:

