VM-Pilot
0.5.0
WPF GUI for spinning up disposable Hyper-V VMs and collecting AutoPilot hardware hashes. Offline mode writes a CSV; Online mode wraps Andrew Taylor's community AutoPilot script for in-VM Intune import.
Minimum PowerShell version
7.0
Installation Options
Owners
Copyright
(c) Mark Orr. All rights reserved.
Package Details
Author(s)
- Mark Orr
Tags
Hyper-V AutoPilot Intune WPF VM Enrollment HWID
Functions
PSEditions
Dependencies
This module has no dependencies.
Release Notes
0.5.0
- VM-Pilot now requires PowerShell 7. The manifest declares PowerShellVersion
7.0 / CompatiblePSEditions Core, so importing under Windows PowerShell 5.1
fails immediately with a clear message instead of misbehaving later.
VMPilot.bat no longer falls back to powershell.exe - it reports that pwsh is
missing and how to install it. The in-VM scripts still target the 5.1 that
ships in the Windows image, since VMs have no pwsh.
- Start-VMPilot checks PowerShell Gallery for a newer version on each run and
offers to install it, matching the Entra-PIM behaviour. It reads the version
from the Gallery page's redirect (~350 ms) rather than Find-Module, updates
with Update-PSResource or Update-Module to match however the module was
installed, and asks before doing anything. Every failure path is silent, so
an offline host or Gallery outage never blocks the GUI. Set
$env:VMPILOT_DISABLE_UPDATE_CHECK = 'true' to skip the check. The prompt runs
before the GUI process spawns, because Start-VMPilot detaches the GUI and
returns immediately - there is no console to prompt on afterwards.
- The offline output folder is renamed C:\Autopilot HWID Collection ->
C:\Autopilot CSV Collection, since it now holds identifier CSVs as well as
hash CSVs. Existing files in the old folder are left where they are.
- Offline mode gains an AUTOPILOT VERSION toggle: "v1 Hash" (unchanged) or
"v2 Identifier", which collects Manufacturer,Model,Serial to
C:\HWID\AutoPilotID-<serial>.csv inside the VM and copies it back to the same
host folder. The file is headerless, matching the format Intune's Device
preparation "Import device identifiers" upload expects. Group Tag hides for
v2 since it does not apply, and the button reads COLLECT IDENTIFIER. Both
formats are WMI-only, so v2 needs no network in the VM.
- Online mode now also injects C:\importv2.bat for Autopilot v2 (Device
preparation). It runs the bundled AutopilotV2Import.ps1, which calls the
community script with -identifier -Online to import the device identifier
(Manufacturer,Model,Serial) instead of a hardware hash. Group Tag and
Assigned User do not apply to v2 - add the device to the Entra security
group targeted by your Device preparation policy after importing.
- The v1 entry point is renamed C:\import.bat -> C:\importv1.bat so the two
flows read as a pair. Its behaviour (hash upload, Group Tag / Assigned User,
profile-assignment poll, reboot into enrollment) is unchanged. VMs built by
earlier versions still have the old C:\import.bat name.
- CLEANUP VMs can now offboard tenant records. A new "Also remove records
from Intune / Autopilot / Entra ID (by serial)" checkbox in the VM Cleanup
dialog deletes each removed VM's cloud identity at the same time as the
local VM (or the local VM alone if left unchecked). It reads each VM's BIOS
serial before deletion - the same serial Autopilot registered.
- New bundled Invoke-VMPilotCloudCleanup.ps1 runner. It hands the serial(s) to
Mark Orr's AutopilotCleanup module (PSGallery) via its Invoke-AutopilotCleanup
orchestrator, which resolves each serial across all three services (Autopilot
-> Intune by serial -> Entra ID by the Autopilot record's Azure AD Device ID),
deletes in the dependency-safe order, and then MONITORS removal live in the
terminal until each service confirms the record is gone. Choose [1] Remove
records only at the module's menu - the VM is destroyed locally, so there is
nothing to wipe. A device missing from a service is a benign no-op (e.g. an
Offline VM whose CSV was never imported).
- Because AutopilotCleanup requires PowerShell 7, the GUI launches the runner in
a pwsh window that signs in to Microsoft Graph (Intune admin required). The
checkbox is disabled with a note if pwsh 7 is not installed.
0.4.2
- Fix VHDX apply progress bar stuck at 0%. The previous approach read
ImageSize from Get-WindowsImage to calculate a denominator for volume-
usage polling, but ImageSize returns 0 for ESD files (all modern Windows
11 ISOs), so the GUI bar never moved. Replaced Expand-WindowsImage and
the DispatcherTimer volume-poller with a direct dism.exe /Apply-Image
call that streams its own CR-delimited progress output. The builder now
emits real 0-100% progress lines that the GUI pipeline consumes directly,
with no dependency on image metadata or disk polling.
0.4.0
- 25H2 only. Dropped 24H2 as a selectable Windows 11 release. The WIN
RELEASE segment is fixed at 25H2, the -Release parameter on the builder
accepts only 25H2, and Get-Win11VHDX.ps1 rejects a 24H2 (build 26100)
ISO instead of building a VHDX the GUI would never load.
- Removed the UUP Dump download path and the bundled Get-UUPDumpISO.ps1
helper. When no cached parent VHDX exists, the GUI now sends you straight
to the "Get Windows 11 Install Media" wizard: download the official ISO
from https://www.microsoft.com/en-us/software-download/windows11, then
build the parent VHDX from it. Once the wizard finishes, the pending VM
build continues automatically.
0.3.0
- New SETUP wizard (green SETUP button in the host GUI): guided steps to
download an official Windows 11 multi-edition ISO from Microsoft, then
builds the parent VHDX from the ISO you pick. Shows live phase status plus
a real apply percentage (from Expand-WindowsImage's progress stream), then
prompts "Build your first VM!" and auto-closes on success.
- Get-Win11VHDX.ps1 auto-detects the Windows release from the ISO image
build (26100 -> 24H2, 26200 -> 25H2) and names the VHDX accordingly
(C:\VMs\Win11-<release>.vhdx) when -OutVhdx is not pinned. New -PickIso
switch opens a native file picker.
- Safer rebuilds: the builder refuses to delete a parent VHDX any VM depends
on (and names the VM) instead of corrupting that VM's differencing disk;
otherwise it dismounts and retries. The SETUP wizard also warns up front
if a parent VHDX already exists or has dependent VMs.
- Offline completion now shows where the hardware-hash CSV was saved on the
host, with an "Open folder" link that selects the file in Explorer.
- Windows PowerShell 5.1 compatibility: all bundled scripts are now UTF-8
with a BOM, so 5.1 reads them as UTF-8 (no-BOM files were parsed as the
legacy Windows-1252 codepage, which broke parsing on non-ASCII characters
like em-dashes). Launch via powershell.exe or pwsh.
- Fix builder-phase progress not advancing: the builder reports phases via
Write-Host (information stream), so the in-runspace capture was changed
from 2>&1 (errors only) to *>&1 (all streams).
0.2.0
- New first-time setup dialog. When no cached parent VHDX exists for the
selected release, the GUI prompts for the ISO source: Download via UUP
Dump (recommended), or Browse for an existing ISO. UUP Dump uses the
Windows Update CDN (*.delivery.mp.microsoft.com), which corporate
firewalls almost never block — solves the "Microsoft software-download
endpoint is blocked" failure mode hit on locked-down Enterprise networks.
- New bundled Get-UUPDumpISO.ps1 helper. Queries the UUP Dump API,
downloads the conversion script pack, patches ConvertConfig.ini with
AutoExit=1 / AddUpdates=0 / ResetBase=0 / SkipWinRE=1 for a fast
non-interactive build (~15-20 min). Pass -IncludeUpdates if you want
the full ~60-90 min build with all cumulative updates integrated.
VM-Pilot's HWID flow doesn't need integrated updates — the hardware
hash is derived from BIOS/vTPM, not OS state.
- Builder Get-Win11VHDX.ps1 now accepts -IsoPath. If supplied, skips the
Fido + download flow entirely and DISM-applies the supplied ISO.
- WIN RELEASE picker is back. Per-release VHDX cache
(C:\VMs\Win11-24H2.vhdx, C:\VMs\Win11-25H2.vhdx) since UUP Dump
reliably serves both 24H2 and 25H2 (where Fido only offered Latest).
- Real % progress meter during UUP file download (aria2c) and
install.wim compression (LZX) — no more guessing at 99%.
- In-VM enrollment GUI rebranded as "VM-Pilot" with "AutoPilot Import"
subtitle, matching the host GUI.
- Hardening: verify DISM apply produced a complete Windows install,
verify bcdboot wrote real UEFI boot files, suppress Windows automount
around every Mount-VHD (kills the "format disk in drive X:" popup),
robust VHDX dismount with retry, kill orphan wimserv/wimlib-imagex
handles before VM creation, force Drive-first boot order on new VMs.
Older releases (0.1.x) are listed at
https://github.com/markorr321/VM-Pilot/releases
FileList
- VM-Pilot.nuspec
- AutopilotEnroll.GUI.ps1
- AutopilotV2Import.ps1
- Get-Win11VHDX.ps1
- Invoke-VMPilotCloudCleanup.ps1
- README.md
- Reset-VMPilot.ps1
- VM-Pilot.psd1
- VM-Pilot.psm1
- VMPilot.bat
- VMPilot.GUI.ps1
- VMPilotCollect.ps1