Autopilot Troubleshooting Tools during ESP

I love Autopilot and always use the enrollment status page (ESP), but sometimes I feel like I’m spending hours looking at the very limited updates and want to know what’s actually happening.

Whilst there is the excellent log collection tool from Microsoft, that’s a snapshot and not a live view.

With that in mind, I have created a script which can run during ESP and provide a GUI with access to a variety of tools:

NOTE: Whilst the script will be running and visible via Alt-Tab, you’ll still need to press Shift-F10 to bump out of the ESP screen and access it. If anyone has a way around this, please let me know!

Update 28/08/2022 – Version 1.1 now released with logic so it doesn’t trigger on current machines outside of OOBE

The buttons are fairly self-explanatory, the script launches Michael Niehaus’s excellent script (which you can read about here)

For the logs, they launch CMTrace (downloaded as part of the original script) directly to the log paths

To deploy the GUI, simply add this script to your PowerShell scripts section in Intune and deploy to Devices (64-bit context)

For those who are interested in how the script works, read on!

First we create a folder:

##Create a folder to store everything
$toolsfolder = "C:\ProgramData\ServiceUI"
If (Test-Path $toolsfolder) {
    Write-Output "$toolsfolder exists. Skipping."
Else {
    Write-Output "The folder '$toolsfolder' doesn't exist. This folder will be used for storing logs created after the script runs. Creating now."
    Start-Sleep 1
    New-Item -Path "$toolsfolder" -ItemType Directory
    Write-Output "The folder $toolsfolder was successfully created."

Set some paths to use later:

##Set download locations
$templateFilePath = "C:\ProgramData\ServiceUI\serviceui.exe"
$cmtraceoutput = "C:\ProgramData\ServiceUI\cmtrace.exe"
$scriptoutput = "C:\ProgramData\ServiceUI\tools.ps1"

Download Michael’s script (and NuGet to avoid prompts, remember this is still in the System context

##To install scripts
set-executionpolicy remotesigned -Force

##Force install NuGet (no popups)
install-packageprovider -Name NuGet -MinimumVersion -Force

##Force install Autopilot Diagnostics (no popups)
Install-Script -Name Get-AutopilotDiagnostics -Force

Now we need to download CMTrace, ServiceUI (for user interaction) and the GUI script

##Download ServiceUI
Invoke-WebRequest `
-Uri "" `
-OutFile $templateFilePath `
-UseBasicParsing `
-Headers @{"Cache-Control"="no-cache"}

##Download CMTrace
Invoke-WebRequest `
-Uri "" `
-OutFile $cmtraceoutput `
-UseBasicParsing `
-Headers @{"Cache-Control"="no-cache"}

##Download tools.ps1
Invoke-WebRequest `
-Uri "" `
-OutFile $scriptoutput `
-UseBasicParsing `
-Headers @{"Cache-Control"="no-cache"}

ServiceUI needs a script to launch and I want to send another Shift-F10 at this point to get the powershell to popup nicely (even if we can’t interact)

##Create powershell script we are launching
$string = @"
start-process powershell.exe -argument '-nologo -noprofile -noexit -executionpolicy bypass -command C:\ProgramData\ServiceUI\tools.ps1 ' -Wait

$string | out-file $file2

Then finally, launch the script:

##Launch script with UI interaction
start-process "C:\ProgramData\ServiceUI\serviceui.exe" -argumentlist ("-process:explorer.exe", 'c:\Windows\System32\WindowsPowershell\v1.0\powershell.exe -Executionpolicy bypass -file C:\ProgramData\ServiceUI\shiftf10.ps1 -windowstyle Hidden')

Hopefully this is useful, if nothing else, it’s nice to watch the logs and see what’s actually happening!

10 thoughts on “Autopilot Troubleshooting Tools during ESP”

  1. Hello Andrew,

    Thanks for your tool, it helps me to develop my own wizard during ESP phase πŸ™‚
    My turn to help you about your blocking point β€œWhilst the script will be running and visible via Alt-Tab, you’ll still need to press Shift-F10 to bump out of the ESP screen and access it. If anyone has a way around this, please let me know!”

    Try this code for your shiftf10.ps1 script:
    ##Create powershell script we are launching
    $string = @”
    # Send Shift+F10 key to open a command prompt
    $WscriptShell = New-Object -ComObject Wscript.Shell
    Start-Sleep 1
    # Wait until cmd process is opened
    Do {Start-Sleep 1} While (-not (Get-Process cmd -ErrorAction SilentlyContinue))
    Start-Sleep 1
    Get-Process cmd | Stop-Process -Force
    start-process powershell.exe -argument β€˜-nologo -noprofile -noexit -executionpolicy bypass -command C:\ProgramData\ServiceUI\tools.ps1 β€˜ -Wait
    $string | out-file $file2


      • This part of the code is broken; firstly, everywhere that $WscriptShell is supposed to appear in shiftf10.ps1 it gets left out because of the string interpolation, so the calls to SendKeys don’t actually work. I think you need to use single quotes rather than double quotes in the definition of $string.

        More importantly, though, the code kills every running instance of cmd.exe, which can cause hard-to-troubleshoot deployment failures.

  2. Thank you, Andrew. Extremely helpful package.

    Do you know a way to also include Fiddler and customize it (enable autosave, exporting client cert and make it available to Fiddler) automatically? I have serious network issues deploying 100++ machines and need to watch the conversation between the management portal, the AD join process (all devices are HAAD joined) and the client while showing ESP.

    • Hi Robert,
      I’ve never tried it myself, but you could package Fiddler with customisations into an MSIX package and pull that down to the device.
      Out of interest, what is the blocker from going straight AAD join? You’ll find it a lot less painful!

  3. How can we make sure we can deploy this to all Autopilot devices, but only during the ESP phase and not when they are on-boarded in Intune and running Windows. I assigned it to my Autopilot testgroup and it showed up in Windows 10 on already deployed devices.

    • Hi, at the moment PowerShell scripts can’t use Device Filters within Intune so you have a couple of options:
      1) Deploy as a Proactive Remediation with filtering, but I’m not sure if that will run early enough
      2) Add some logic into the script to detect if a machine has been built, this is what I’ve used before, if it detects Intune installed apps, we can assume the machine is already existing:
      $intunepath = “HKLM:\SOFTWARE\Microsoft\IntuneManagementExtension\Win32Apps”
      $intunecomplete = @(Get-ChildItem $intunepath).count
      if ($intunecomplete -eq 0) {
      ##Add script here


Leave a Comment