Add experimental VM networking opt-in for Hyper-V builds

The Hyper-V switch selection in the UI previously did not connect the build VM to the network during provisioning. Since internet-connected Sysprep and capture flows are still experimental, this introduces an explicit "Enable VM Networking" checkbox to the Hyper-V Settings page that defaults to off.

- Adds the `-EnableVMNetworking` parameter to BuildFFUVM.ps1 to conditionally attach the Hyper-V network adapter during VM creation.
- Persists the setting through FFU config files and blocks UI execution if enabled without a valid switch.
- Refactors WPF event handlers in FFUUI.Core to fix dropdown scoping errors.
- Updates documentation and the sample configuration file to reflect the new behavior.
This commit is contained in:
rbalsleyMSFT
2026-03-30 16:37:53 -07:00
parent f838ef3779
commit 78212f06d7
11 changed files with 128 additions and 27 deletions
+52 -8
View File
@@ -90,6 +90,9 @@ Path to a JSON file that specifies which drivers to download.
.PARAMETER ExportConfigFile
Path to a JSON file to export the parameters used for the script.
.PARAMETER EnableVMNetworking
When set to $true, connects the build VM to the Hyper-V virtual switch named in -VMSwitchName during provisioning. Default is $false because internet-connected Sysprep is experimental.
.PARAMETER FFUCaptureLocation
Path to the folder where the captured FFU will be stored. Default is $FFUDevelopmentPath\FFU.
@@ -223,7 +226,7 @@ Path to a JSON file containing a list of user-defined applications to install. D
Default is $FFUDevelopmentPath\VM. This is the location of the VHDX that gets created where Windows will be installed to.
.PARAMETER VMSwitchName
Name of the Hyper-V virtual switch. Optional when building with InstallApps. Provide it only if the VM needs network connectivity during provisioning.
Name of the Hyper-V virtual switch used when -EnableVMNetworking is set to $true. Provide it only if the VM needs network connectivity during provisioning.
.PARAMETER WindowsArch
String value of 'x86', 'x64', or 'arm64'. This is used to identify which architecture of Windows to download. Default is 'x64'.
@@ -317,6 +320,7 @@ param(
[uint64]$Memory = 4GB,
[uint64]$Disksize = 50GB,
[int]$Processors = 4,
[bool]$EnableVMNetworking,
[string]$VMSwitchName,
[string]$VMLocation,
[string]$FFUPrefix = '_FFU',
@@ -501,6 +505,13 @@ if ($ConfigFile -and (Test-Path -Path $ConfigFile)) {
}
}
$vmSwitchWasExplicitlyBound = $PSBoundParameters.ContainsKey('VMSwitchName')
$enableVmNetworkingWasExplicitlyBound = $PSBoundParameters.ContainsKey('EnableVMNetworking')
if (-not $EnableVMNetworking -and $vmSwitchWasExplicitlyBound -and -not $enableVmNetworkingWasExplicitlyBound) {
$EnableVMNetworking = $true
WriteLog 'EnableVMNetworking not explicitly set. Enabling VM networking because -VMSwitchName was supplied on the command line.'
}
# Validate that the selected Windows SKU is compatible with the chosen Windows release and ensure an ISO is provided for unsupported releases
$clientSKUs = @(
'Home',
@@ -2899,6 +2910,27 @@ function New-FFUVM {
$VM = New-VM -Name $VMName -Path $VMPath -MemoryStartupBytes $memory -VHDPath $VHDXPath -Generation 2
Set-VMProcessor -VMName $VMName -Count $processors
# Connect the VM to the requested switch only when the experimental networking flag is enabled.
if ($EnableVMNetworking) {
$primaryVmNetworkAdapter = Get-VMNetworkAdapter -VMName $VMName -ErrorAction SilentlyContinue | Select-Object -First 1
if ($null -ne $primaryVmNetworkAdapter) {
if ($primaryVmNetworkAdapter.SwitchName -eq $VMSwitchName) {
WriteLog "VM '$VMName' is already connected to Hyper-V switch '$VMSwitchName'."
}
else {
Connect-VMNetworkAdapter -VMNetworkAdapter $primaryVmNetworkAdapter -SwitchName $VMSwitchName -ErrorAction Stop
WriteLog "Connected VM '$VMName' to Hyper-V switch '$VMSwitchName'."
}
}
else {
Add-VMNetworkAdapter -VMName $VMName -SwitchName $VMSwitchName -Name 'FFUNetworkAdapter' -ErrorAction Stop | Out-Null
WriteLog "Added VM network adapter for '$VMName' on Hyper-V switch '$VMSwitchName'."
}
}
else {
WriteLog "VM networking is disabled for '$VMName'."
}
#Mount AppsISO
Add-VMDvdDrive -VMName $VMName -Path $AppsISO
@@ -5500,14 +5532,26 @@ if ($CopyUnattend) {
if (($InstallOffice -eq $true) -and ($InstallApps -eq $false)) {
throw "If variable InstallOffice is set to `$true, InstallApps must also be set to `$true."
}
if ($VMSwitchName) {
WriteLog "Validating -VMSwitchName $VMSwitchName"
#Check $VMSwitchName by using Get-VMSwitch
$VMSwitch = Get-VMSwitch -Name $VMSwitchName -ErrorAction SilentlyContinue
if (-not $VMSwitch) {
throw "-VMSwitchName $VMSwitchName not found. Please check the -VMSwitchName parameter and try again."
if ($EnableVMNetworking) {
if ($InstallApps -eq $false) {
WriteLog 'EnableVMNetworking is set to true, but InstallApps is false. No VM will be created, so VM networking will be ignored.'
}
WriteLog '-VMSwitchName validation complete'
else {
if ([string]::IsNullOrWhiteSpace($VMSwitchName)) {
throw '-EnableVMNetworking requires -VMSwitchName. Select or enter a Hyper-V switch and try again.'
}
WriteLog "Experimental VM networking enabled. Validating -VMSwitchName $VMSwitchName"
#Check $VMSwitchName by using Get-VMSwitch
$VMSwitch = Get-VMSwitch -Name $VMSwitchName -ErrorAction SilentlyContinue
if (-not $VMSwitch) {
throw "-VMSwitchName $VMSwitchName not found. Please check the -VMSwitchName parameter and try again."
}
WriteLog '-EnableVMNetworking validation complete'
}
}
elseif ($VMSwitchName) {
WriteLog "VM networking is disabled. Stored -VMSwitchName $VMSwitchName will not be used unless -EnableVMNetworking is `$true."
}
if (-not ($ISOPath) -and ($OptionalFeatures -like '*netfx3*')) {