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 .PARAMETER ExportConfigFile
Path to a JSON file to export the parameters used for the script. 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 .PARAMETER FFUCaptureLocation
Path to the folder where the captured FFU will be stored. Default is $FFUDevelopmentPath\FFU. 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. Default is $FFUDevelopmentPath\VM. This is the location of the VHDX that gets created where Windows will be installed to.
.PARAMETER VMSwitchName .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 .PARAMETER WindowsArch
String value of 'x86', 'x64', or 'arm64'. This is used to identify which architecture of Windows to download. Default is 'x64'. 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]$Memory = 4GB,
[uint64]$Disksize = 50GB, [uint64]$Disksize = 50GB,
[int]$Processors = 4, [int]$Processors = 4,
[bool]$EnableVMNetworking,
[string]$VMSwitchName, [string]$VMSwitchName,
[string]$VMLocation, [string]$VMLocation,
[string]$FFUPrefix = '_FFU', [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 # Validate that the selected Windows SKU is compatible with the chosen Windows release and ensure an ISO is provided for unsupported releases
$clientSKUs = @( $clientSKUs = @(
'Home', 'Home',
@@ -2899,6 +2910,27 @@ function New-FFUVM {
$VM = New-VM -Name $VMName -Path $VMPath -MemoryStartupBytes $memory -VHDPath $VHDXPath -Generation 2 $VM = New-VM -Name $VMName -Path $VMPath -MemoryStartupBytes $memory -VHDPath $VHDXPath -Generation 2
Set-VMProcessor -VMName $VMName -Count $processors 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 #Mount AppsISO
Add-VMDvdDrive -VMName $VMName -Path $AppsISO Add-VMDvdDrive -VMName $VMName -Path $AppsISO
@@ -5500,14 +5532,26 @@ if ($CopyUnattend) {
if (($InstallOffice -eq $true) -and ($InstallApps -eq $false)) { if (($InstallOffice -eq $true) -and ($InstallApps -eq $false)) {
throw "If variable InstallOffice is set to `$true, InstallApps must also be set to `$true." throw "If variable InstallOffice is set to `$true, InstallApps must also be set to `$true."
} }
if ($VMSwitchName) { if ($EnableVMNetworking) {
WriteLog "Validating -VMSwitchName $VMSwitchName" if ($InstallApps -eq $false) {
#Check $VMSwitchName by using Get-VMSwitch WriteLog 'EnableVMNetworking is set to true, but InstallApps is false. No VM will be created, so VM networking will be ignored.'
$VMSwitch = Get-VMSwitch -Name $VMSwitchName -ErrorAction SilentlyContinue
if (-not $VMSwitch) {
throw "-VMSwitchName $VMSwitchName not found. Please check the -VMSwitchName parameter and try again."
} }
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*')) { if (-not ($ISOPath) -and ($OptionalFeatures -like '*netfx3*')) {
+7
View File
@@ -425,6 +425,13 @@ $script:uiState.Controls.btnRun.Add_Click({
return return
} }
if ($config.EnableVMNetworking -and $config.InstallApps -and [string]::IsNullOrWhiteSpace([string]$config.VMSwitchName)) {
[System.Windows.MessageBox]::Show("Select or enter a VM Switch Name before enabling VM networking.", "VM Switch Required", "OK", "Warning") | Out-Null
$btnRun.IsEnabled = $true
$script:uiState.Controls.txtStatus.Text = "Build canceled: VM switch required for experimental networking."
return
}
$configFilePath = Join-Path $config.FFUDevelopmentPath "\config\FFUConfig.json" $configFilePath = Join-Path $config.FFUDevelopmentPath "\config\FFUConfig.json"
# Sort top-level keys alphabetically for consistent output # Sort top-level keys alphabetically for consistent output
$sortedConfig = [ordered]@{} $sortedConfig = [ordered]@{}
+9 -5
View File
@@ -315,11 +315,15 @@
<!-- PAGE: Hyper-V Settings --> <!-- PAGE: Hyper-V Settings -->
<ScrollViewer x:Name="pageHyperV" VerticalScrollBarVisibility="Auto" Visibility="Collapsed"> <ScrollViewer x:Name="pageHyperV" VerticalScrollBarVisibility="Auto" Visibility="Collapsed">
<StackPanel Margin="16,0,16,16"> <StackPanel Margin="16,0,16,16">
<!-- VM Switch Name --> <!-- Enable VM Networking -->
<TextBlock Text="VM Switch Name" Margin="0,0,0,8" ToolTip="Name of the Hyper-V virtual switch. If $InstallApps is set to $true, this must be set. This is required to capture the FFU from the VM. The default is '*external*', but you will likely need to change this."/> <CheckBox x:Name="chkEnableVMNetworking" Content="Enable VM Networking (Experimental)" Margin="0,0,0,12" ToolTip="Connect the build VM to the selected Hyper-V switch during provisioning. Leave this off for the default offline build path because internet-connected Sysprep is still experimental."/>
<ComboBox x:Name="cmbVMSwitchName" HorizontalAlignment="Stretch" Margin="0,0,0,20" ToolTip="Name of the Hyper-V virtual switch. If $InstallApps is set to $true, this must be set. This is required to capture the FFU from the VM. The default is '*external*', but you will likely need to change this."/> <StackPanel x:Name="spVMNetworkingSettings" Margin="0,0,0,20" IsEnabled="False">
<!-- Custom VM Switch Name --> <!-- VM Switch Name -->
<TextBox x:Name="txtCustomVMSwitchName" HorizontalAlignment="Stretch" Visibility="Collapsed" Margin="0,0,0,20" ToolTip="Enter your custom VM Switch Name if 'Other' is selected."/> <TextBlock Text="VM Switch Name" Margin="0,0,0,8" ToolTip="Select or enter the Hyper-V virtual switch to use when experimental VM networking is enabled."/>
<ComboBox x:Name="cmbVMSwitchName" HorizontalAlignment="Stretch" Margin="0,0,0,20" ToolTip="Select or enter the Hyper-V virtual switch to use when experimental VM networking is enabled."/>
<!-- Custom VM Switch Name -->
<TextBox x:Name="txtCustomVMSwitchName" HorizontalAlignment="Stretch" Visibility="Collapsed" Margin="0,0,0,0" ToolTip="Enter your custom VM Switch Name if 'Other' is selected."/>
</StackPanel>
<!-- Disk Size (GB) --> <!-- Disk Size (GB) -->
<TextBlock Text="Disk Size (GB)" Margin="0,0,0,8" ToolTip="Size of the virtual hard disk for the virtual machine. Default is a 50GB dynamic disk."/> <TextBlock Text="Disk Size (GB)" Margin="0,0,0,8" ToolTip="Size of the virtual hard disk for the virtual machine. Default is a 50GB dynamic disk."/>
<TextBox x:Name="txtDiskSize" HorizontalAlignment="Stretch" Text="50" Margin="0,0,0,20" ToolTip="Size of the virtual hard disk for the virtual machine. Default is a 50GB dynamic disk."/> <TextBox x:Name="txtDiskSize" HorizontalAlignment="Stretch" Text="50" Margin="0,0,0,20" ToolTip="Size of the virtual hard disk for the virtual machine. Default is a 50GB dynamic disk."/>
@@ -44,6 +44,7 @@ function Get-UIConfig {
DownloadDrivers = $State.Controls.chkDownloadDrivers.IsChecked DownloadDrivers = $State.Controls.chkDownloadDrivers.IsChecked
DriversFolder = $State.Controls.txtDriversFolder.Text DriversFolder = $State.Controls.txtDriversFolder.Text
DriversJsonPath = $State.Controls.txtDriversJsonPath.Text DriversJsonPath = $State.Controls.txtDriversJsonPath.Text
EnableVMNetworking = $State.Controls.chkEnableVMNetworking.IsChecked
FFUCaptureLocation = $State.Controls.txtFFUCaptureLocation.Text FFUCaptureLocation = $State.Controls.txtFFUCaptureLocation.Text
FFUDevelopmentPath = $State.Controls.txtFFUDevPath.Text FFUDevelopmentPath = $State.Controls.txtFFUDevPath.Text
FFUPrefix = $State.Controls.txtVMNamePrefix.Text FFUPrefix = $State.Controls.txtVMNamePrefix.Text
@@ -466,6 +467,7 @@ function Update-UIFromConfig {
Set-UIValue -ControlName 'chkRemoveDownloadedESD' -PropertyName 'IsChecked' -ConfigObject $ConfigContent -ConfigKey 'RemoveDownloadedESD' -State $State Set-UIValue -ControlName 'chkRemoveDownloadedESD' -PropertyName 'IsChecked' -ConfigObject $ConfigContent -ConfigKey 'RemoveDownloadedESD' -State $State
# Hyper-V Settings # Hyper-V Settings
Set-UIValue -ControlName 'chkEnableVMNetworking' -PropertyName 'IsChecked' -ConfigObject $ConfigContent -ConfigKey 'EnableVMNetworking' -State $State
Select-VMSwitchFromConfig -State $State -ConfigContent $ConfigContent Select-VMSwitchFromConfig -State $State -ConfigContent $ConfigContent
Set-UIValue -ControlName 'txtDiskSize' -PropertyName 'Text' -ConfigObject $ConfigContent -ConfigKey 'Disksize' -TransformValue { param($val) $val / 1GB } -State $State Set-UIValue -ControlName 'txtDiskSize' -PropertyName 'Text' -ConfigObject $ConfigContent -ConfigKey 'Disksize' -TransformValue { param($val) $val / 1GB } -State $State
Set-UIValue -ControlName 'txtMemory' -PropertyName 'Text' -ConfigObject $ConfigContent -ConfigKey 'Memory' -TransformValue { param($val) $val / 1GB } -State $State Set-UIValue -ControlName 'txtMemory' -PropertyName 'Text' -ConfigObject $ConfigContent -ConfigKey 'Memory' -TransformValue { param($val) $val / 1GB } -State $State
@@ -473,6 +475,10 @@ function Update-UIFromConfig {
Set-UIValue -ControlName 'txtVMLocation' -PropertyName 'Text' -ConfigObject $ConfigContent -ConfigKey 'VMLocation' -State $State Set-UIValue -ControlName 'txtVMLocation' -PropertyName 'Text' -ConfigObject $ConfigContent -ConfigKey 'VMLocation' -State $State
Set-UIValue -ControlName 'txtVMNamePrefix' -PropertyName 'Text' -ConfigObject $ConfigContent -ConfigKey 'FFUPrefix' -State $State Set-UIValue -ControlName 'txtVMNamePrefix' -PropertyName 'Text' -ConfigObject $ConfigContent -ConfigKey 'FFUPrefix' -State $State
Set-UIValue -ControlName 'cmbLogicalSectorSize' -PropertyName 'SelectedItem' -ConfigObject $ConfigContent -ConfigKey 'LogicalSectorSizeBytes' -TransformValue { param($val) $val.ToString() } -State $State Set-UIValue -ControlName 'cmbLogicalSectorSize' -PropertyName 'SelectedItem' -ConfigObject $ConfigContent -ConfigKey 'LogicalSectorSizeBytes' -TransformValue { param($val) $val.ToString() } -State $State
$State.Controls.spVMNetworkingSettings.IsEnabled = $true -eq $State.Controls.chkEnableVMNetworking.IsChecked
if (-not ($true -eq $State.Controls.chkEnableVMNetworking.IsChecked)) {
$State.Controls.txtCustomVMSwitchName.Visibility = 'Collapsed'
}
# Windows Settings # Windows Settings
Set-UIValue -ControlName 'txtISOPath' -PropertyName 'Text' -ConfigObject $ConfigContent -ConfigKey 'ISOPath' -State $State Set-UIValue -ControlName 'txtISOPath' -PropertyName 'Text' -ConfigObject $ConfigContent -ConfigKey 'ISOPath' -State $State
@@ -5,6 +5,28 @@
This module is dedicated to managing user interactions within the FFU Builder UI. It contains the Register-EventHandlers function, which connects UI controls defined in the XAML to their corresponding actions in the PowerShell backend. This includes handling button clicks, text input validation, checkbox state changes, and list view interactions across all tabs, effectively wiring up the application's front-end to its core logic. This module is dedicated to managing user interactions within the FFU Builder UI. It contains the Register-EventHandlers function, which connects UI controls defined in the XAML to their corresponding actions in the PowerShell backend. This includes handling button clicks, text input validation, checkbox state changes, and list view interactions across all tabs, effectively wiring up the application's front-end to its core logic.
#> #>
function Update-VMNetworkingControls {
param([PSCustomObject]$State)
$isVmNetworkingEnabled = $true -eq $State.Controls.chkEnableVMNetworking.IsChecked
$State.Controls.spVMNetworkingSettings.IsEnabled = $isVmNetworkingEnabled
if (-not $isVmNetworkingEnabled) {
$State.Controls.txtCustomVMSwitchName.Visibility = 'Collapsed'
return
}
if ($State.Controls.cmbVMSwitchName.SelectedItem -eq 'Other') {
$State.Controls.txtCustomVMSwitchName.Visibility = 'Visible'
if ([string]::IsNullOrWhiteSpace($State.Controls.txtCustomVMSwitchName.Text) -and $null -ne $State.Data.customVMSwitchName) {
$State.Controls.txtCustomVMSwitchName.Text = $State.Data.customVMSwitchName
}
}
else {
$State.Controls.txtCustomVMSwitchName.Visibility = 'Collapsed'
}
}
function Register-EventHandlers { function Register-EventHandlers {
param([PSCustomObject]$State) param([PSCustomObject]$State)
WriteLog "Registering UI event handlers..." WriteLog "Registering UI event handlers..."
@@ -379,22 +401,27 @@ function Register-EventHandlers {
}) })
# Hyper-V tab event handlers # Hyper-V tab event handlers
$State.Controls.chkEnableVMNetworking.Add_Checked({
param($eventSource, $routedEventArgs)
$window = [System.Windows.Window]::GetWindow($eventSource)
$localState = $window.Tag
Update-VMNetworkingControls -State $localState
})
$State.Controls.chkEnableVMNetworking.Add_Unchecked({
param($eventSource, $routedEventArgs)
$window = [System.Windows.Window]::GetWindow($eventSource)
$localState = $window.Tag
Update-VMNetworkingControls -State $localState
})
$State.Controls.cmbVMSwitchName.Add_SelectionChanged({ $State.Controls.cmbVMSwitchName.Add_SelectionChanged({
param($eventSource, $selectionChangedEventArgs) param($eventSource, $selectionChangedEventArgs)
# The state object is available via the parent window's Tag property # The state object is available via the parent window's Tag property
$window = [System.Windows.Window]::GetWindow($eventSource) $window = [System.Windows.Window]::GetWindow($eventSource)
$localState = $window.Tag $localState = $window.Tag
$selectedItem = $eventSource.SelectedItem Update-VMNetworkingControls -State $localState
if ($selectedItem -eq 'Other') {
$localState.Controls.txtCustomVMSwitchName.Visibility = 'Visible'
if ([string]::IsNullOrWhiteSpace($localState.Controls.txtCustomVMSwitchName.Text) -and $null -ne $localState.Data.customVMSwitchName) {
$localState.Controls.txtCustomVMSwitchName.Text = $localState.Data.customVMSwitchName
}
}
else {
$localState.Controls.txtCustomVMSwitchName.Visibility = 'Collapsed'
}
}) })
# Persist custom VM switch name when user edits it while 'Other' is selected # Persist custom VM switch name when user edits it while 'Other' is selected
@@ -205,6 +205,8 @@ function Initialize-UIControls {
$State.Controls.txtStatus = $window.FindName('txtStatus') $State.Controls.txtStatus = $window.FindName('txtStatus')
$State.Controls.pbOverallProgress = $window.FindName('progressBar') $State.Controls.pbOverallProgress = $window.FindName('progressBar')
$State.Controls.txtOverallStatus = $window.FindName('txtStatus') $State.Controls.txtOverallStatus = $window.FindName('txtStatus')
$State.Controls.chkEnableVMNetworking = $window.FindName('chkEnableVMNetworking')
$State.Controls.spVMNetworkingSettings = $window.FindName('spVMNetworkingSettings')
$State.Controls.cmbVMSwitchName = $window.FindName('cmbVMSwitchName') $State.Controls.cmbVMSwitchName = $window.FindName('cmbVMSwitchName')
$State.Controls.txtCustomVMSwitchName = $window.FindName('txtCustomVMSwitchName') $State.Controls.txtCustomVMSwitchName = $window.FindName('txtCustomVMSwitchName')
$State.Controls.txtFFUDevPath = $window.FindName('txtFFUDevPath') $State.Controls.txtFFUDevPath = $window.FindName('txtFFUDevPath')
@@ -345,7 +347,6 @@ function Initialize-VMSwitchData {
$State.Controls.cmbVMSwitchName.Items.Add('Other') | Out-Null $State.Controls.cmbVMSwitchName.Items.Add('Other') | Out-Null
if ($State.Controls.cmbVMSwitchName.Items.Count -gt 1) { if ($State.Controls.cmbVMSwitchName.Items.Count -gt 1) {
$State.Controls.cmbVMSwitchName.SelectedIndex = 0 $State.Controls.cmbVMSwitchName.SelectedIndex = 0
$firstSwitch = $State.Controls.cmbVMSwitchName.SelectedItem
$State.Controls.txtCustomVMSwitchName.Visibility = 'Collapsed' $State.Controls.txtCustomVMSwitchName.Visibility = 'Collapsed'
} }
else { else {
@@ -398,7 +399,9 @@ function Initialize-UIDefaults {
Update-BitsPrioritySetting -State $State Update-BitsPrioritySetting -State $State
# Hyper-V Settings defaults from General Defaults # Hyper-V Settings defaults from General Defaults
$State.Controls.chkEnableVMNetworking.IsChecked = $State.Defaults.generalDefaults.EnableVMNetworking
Initialize-VMSwitchData -State $State Initialize-VMSwitchData -State $State
$State.Controls.spVMNetworkingSettings.IsEnabled = $true -eq $State.Controls.chkEnableVMNetworking.IsChecked
$State.Controls.txtDiskSize.Text = $State.Defaults.generalDefaults.DiskSizeGB $State.Controls.txtDiskSize.Text = $State.Defaults.generalDefaults.DiskSizeGB
$State.Controls.txtMemory.Text = $State.Defaults.generalDefaults.MemoryGB $State.Controls.txtMemory.Text = $State.Defaults.generalDefaults.MemoryGB
$State.Controls.txtProcessors.Text = $State.Defaults.generalDefaults.Processors $State.Controls.txtProcessors.Text = $State.Defaults.generalDefaults.Processors
@@ -140,6 +140,7 @@ function Get-GeneralDefaults {
RemoveUpdates = $false RemoveUpdates = $false
RemoveDownloadedESD = $true RemoveDownloadedESD = $true
# Hyper-V Settings Defaults # Hyper-V Settings Defaults
EnableVMNetworking = $false
DiskSizeGB = 50 DiskSizeGB = 50
MemoryGB = 4 MemoryGB = 4
Processors = 4 Processors = 4
Binary file not shown.
+7 -1
View File
@@ -11,11 +11,17 @@ parent: UI Overview
![1759533067934](image/ui_overview/1759533067934.png) ![1759533067934](image/ui_overview/1759533067934.png)
## Enable VM Networking (Experimental)
Controls whether the build VM is connected to a Hyper-V switch during provisioning.
Leave this off for the default offline build path. Turn it on only if you want to test internet-connected builds and understand there may be Sysprep or capture issues.
## VM Switch Name ## VM Switch Name
Drop down of detected VM Switches. There's also an **Other** option which allows you to specify a VM Switch Name. The other option is useful in scenarios where the machine you're running the UI from isn't going to be the machine where you plan to build the FFU from. Drop down of detected VM Switches. There's also an **Other** option which allows you to specify a VM Switch Name. The other option is useful in scenarios where the machine you're running the UI from isn't going to be the machine where you plan to build the FFU from.
This setting is now optional for FFU capture itself. VM-based builds still capture from the host-side VHDX after the VM shuts down, so you only need a switch when the VM requires network connectivity during provisioning. This setting is only used when **Enable VM Networking (Experimental)** is turned on. VM-based builds still capture from the host-side VHDX after the VM shuts down, so you only need a switch when the VM requires network connectivity during provisioning.
## Disk Size (GB) ## Disk Size (GB)
+2 -1
View File
@@ -44,6 +44,7 @@ This table lists all top-level parameters in BuildFFUVM.ps1.
| -Disksize | uint64 | Disk Size (GB) | Size of the virtual hard disk for the virtual machine. Default is a 50GB dynamic disk. | | -Disksize | uint64 | Disk Size (GB) | Size of the virtual hard disk for the virtual machine. Default is a 50GB dynamic disk. |
| -DriversFolder | string | Drivers Folder | Path to the drivers folder. Default is $FFUDevelopmentPath\Drivers. | | -DriversFolder | string | Drivers Folder | Path to the drivers folder. Default is $FFUDevelopmentPath\Drivers. |
| -DriversJsonPath | string | Drivers.json Path | Path to a JSON file that specifies which drivers to download. | | -DriversJsonPath | string | Drivers.json Path | Path to a JSON file that specifies which drivers to download. |
| -EnableVMNetworking | bool | Enable VM Networking (Experimental) | When set to $true, connects the build VM to the selected Hyper-V switch during provisioning. Default is $false because internet-connected Sysprep is experimental. |
| -ExportConfigFile | string | Save Config File | Path to a JSON file to export the parameters used for the script. | | -ExportConfigFile | string | Save Config File | Path to a JSON file to export the parameters used for the script. |
| -FFUCaptureLocation | string | FFU Capture Location | Path to the folder where the captured FFU will be stored. Default is $FFUDevelopmentPath\FFU. | | -FFUCaptureLocation | string | FFU Capture Location | Path to the folder where the captured FFU will be stored. Default is $FFUDevelopmentPath\FFU. |
| -FFUDevelopmentPath | string | FFU Development Path | Path to the FFU development folder. Default is $PSScriptRoot. | | -FFUDevelopmentPath | string | FFU Development Path | Path to the FFU development folder. Default is $PSScriptRoot. |
@@ -86,7 +87,7 @@ This table lists all top-level parameters in BuildFFUVM.ps1.
| -UserAgent | string | CLI only (no UI control) | User agent string to use when downloading files. | | -UserAgent | string | CLI only (no UI control) | User agent string to use when downloading files. |
| -UserAppListPath | string | Application Path (derived UserAppList.json) | Path to a JSON file containing a list of user-defined applications to install. Default is $FFUDevelopmentPath\Apps\UserAppList.json. | | -UserAppListPath | string | Application Path (derived UserAppList.json) | Path to a JSON file containing a list of user-defined applications to install. Default is $FFUDevelopmentPath\Apps\UserAppList.json. |
| -VMLocation | string | VM Location | Default is $FFUDevelopmentPath\VM. This is the location of the VHDX that gets created where Windows will be installed to. | | -VMLocation | string | VM Location | Default is $FFUDevelopmentPath\VM. This is the location of the VHDX that gets created where Windows will be installed to. |
| -VMSwitchName | string | VM Switch Name + Custom VM Switch Name (when Other selected) | Name of the Hyper-V virtual switch. Provide it when the VM needs network connectivity during provisioning. | | -VMSwitchName | string | VM Switch Name + Custom VM Switch Name (when Other selected) | Name of the Hyper-V virtual switch used when -EnableVMNetworking is set to $true. |
| -WindowsArch | string | Windows Architecture | String value of 'x86', 'x64', or 'arm64'. This is used to identify which architecture of Windows to download. Default is 'x64'. | | -WindowsArch | string | Windows Architecture | String value of 'x86', 'x64', or 'arm64'. This is used to identify which architecture of Windows to download. Default is 'x64'. |
| -WindowsLang | string | Windows Language | String value in language-region format (e.g., 'en-us'). This is used to identify which language of media to download. Default is 'en-us'. | | -WindowsLang | string | Windows Language | String value in language-region format (e.g., 'en-us'). This is used to identify which language of media to download. Default is 'en-us'. |
| -WindowsRelease | int | Windows Release | Integer value of 10, 11, 2016, 2019, 2021, 2022, 2024, or 2025. This is used to identify which Windows client/LTSC/server release to use. Default is 11. | | -WindowsRelease | int | Windows Release | Integer value of 10, 11, 2016, 2019, 2021, 2022, 2024, or 2025. This is used to identify which Windows client/LTSC/server release to use. Default is 11. |
+3 -1
View File
@@ -45,7 +45,9 @@ Follow the [prerequisites](/FFU/prerequisites.html) documentation before getting
Click the Hyper-V Settings tab Click the Hyper-V Settings tab
You should be able to keep these settings at the defaults. If the VM needs network connectivity during provisioning, make sure the switch you created in the prerequisites section is listed under VM Switch Name. If the build does not need VM networking, you can leave the switch unset. You should be able to keep these settings at the defaults. **Enable VM Networking (Experimental)** is off by default and should stay off unless you specifically want to test an internet-connected VM during provisioning.
If you turn on **Enable VM Networking (Experimental)**, make sure the switch you created in the prerequisites section is listed under **VM Switch Name**. If the build does not create a VM, this setting has no effect.
One setting you might need to set is the Logical Sector Size. 512 is the default and that's what most physical disks use today. However 4kn drives and UFS drives use 4k sector sizes, which would require you to select 4096. For now, select 512. If you have issues during deployment, there is error logging that will tell you if you need to set to 4096 on your device. One setting you might need to set is the Logical Sector Size. 512 is the default and that's what most physical disks use today. However 4kn drives and UFS drives use 4k sector sizes, which would require you to select 4096. For now, select 512. If you have issues during deployment, there is error logging that will tell you if you need to set to 4096 on your device.