Files
FFU/FFUDevelopment/BuildFFUVM_UI.ps1
T
rbalsleyMSFT f9a8e3149f Adds a "Verbose" checkbox to the UI, allowing users to enable write-verbose output from the underlying build script.
This helps in troubleshooting the FFU build process by providing more detailed output to the console. The verbose setting is saved to and loaded from the configuration file.
2025-07-09 09:50:26 -07:00

186 lines
7.5 KiB
PowerShell

[CmdletBinding()]
[System.STAThread()]
param()
# Check PowerShell Version
if ($PSVersionTable.PSVersion.Major -lt 7) {
Write-Error "PowerShell 7 or later is required to run this script."
exit 1
}
# Creating custom state object to hold UI state and data
$FFUDevelopmentPath = 'C:\FFUDevelopment' # hard coded for testing
$script:uiState = [PSCustomObject]@{
FFUDevelopmentPath = $FFUDevelopmentPath;
Window = $null;
Controls = @{
featureCheckBoxes = @{};
UpdateInstallAppsBasedOnUpdates = $null
};
Data = @{
allDriverModels = [System.Collections.Generic.List[PSCustomObject]]::new();
appsScriptVariablesDataList = [System.Collections.Generic.List[PSCustomObject]]::new();
versionData = $null;
vmSwitchMap = @{}
};
Flags = @{
installAppsForcedByUpdates = $false;
prevInstallAppsStateBeforeUpdates = $null;
installAppsCheckedByOffice = $false;
lastSortProperty = $null;
lastSortAscending = $true
};
Defaults = @{};
LogFilePath = "$FFUDevelopmentPath\FFUDevelopment_UI.log"
}
# Remove any existing modules to avoid conflicts
if (Get-Module -Name 'FFU.Common.Core' -ErrorAction SilentlyContinue) {
Remove-Module -Name 'FFU.Common.Core' -Force
}
if (Get-Module -Name 'FFUUI.Core' -ErrorAction SilentlyContinue) {
Remove-Module -Name 'FFUUI.Core' -Force
}
# Import Modules
Import-Module "$PSScriptRoot\FFU.Common" -Force
Import-Module "$PSScriptRoot\FFUUI.Core" -Force
# Set the log path
Set-CommonCoreLogPath -Path $script:uiState.LogFilePath
# Setting long path support - this prevents issues where some applications have deep directory structures
# and driver extraction fails due to long paths.
$script:uiState.Flags.originalLongPathsValue = $null # Store original value
try {
$script:uiState.Flags.originalLongPathsValue = Get-ItemPropertyValue -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -ErrorAction SilentlyContinue
}
catch {
# Key or value might not exist, which is fine.
WriteLog "Could not read initial LongPathsEnabled value (may not exist)."
}
# Enable long paths if not already enabled
if ($script:uiState.Flags.originalLongPathsValue -ne 1) {
try {
WriteLog 'LongPathsEnabled is not set to 1. Setting it to 1 for the duration of this script.'
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -Value 1 -Force
WriteLog 'LongPathsEnabled set to 1.'
}
catch {
WriteLog "Error setting LongPathsEnabled registry key: $($_.Exception.Message). Long path issues might persist."
}
}
else {
WriteLog "LongPathsEnabled is already set to 1."
}
if (Test-Path -Path $script:uiState.LogFilePath) {
Remove-item -Path $script:uiState.LogFilePath -Force
}
Add-Type -AssemblyName WindowsBase
Add-Type -AssemblyName PresentationCore, PresentationFramework
Add-Type -AssemblyName System.Windows.Forms
# Load XAML
$xamlPath = Join-Path $PSScriptRoot "BuildFFUVM_UI.xaml"
if (-not (Test-Path $xamlPath)) {
Write-Error "XAML file not found: $xamlPath"
return
}
$xamlString = Get-Content $xamlPath -Raw
$reader = New-Object System.IO.StringReader($xamlString)
$xmlReader = [System.Xml.XmlReader]::Create($reader)
$window = [Windows.Markup.XamlReader]::Load($xmlReader)
$window.Add_Loaded({
# Pass the state object to all initialization functions
$script:uiState.Window = $window
$window.Tag = $script:uiState
Initialize-UIControls -State $script:uiState
Initialize-UIDefaults -State $script:uiState
Initialize-DynamicUIElements -State $script:uiState
Register-EventHandlers -State $script:uiState
})
# Button: Build FFU
$btnRun = $window.FindName('btnRun')
$btnRun.Add_Click({
try {
$progressBar = $script:uiState.Controls.pbOverallProgress
$txtStatus = $script:uiState.Controls.txtStatus
$progressBar.Visibility = 'Visible'
$txtStatus.Text = "Starting FFU build..."
$config = Get-UIConfig -State $script:uiState
$configFilePath = Join-Path $config.FFUDevelopmentPath "\config\FFUConfig.json"
$config | ConvertTo-Json -Depth 10 | Set-Content $configFilePath -Encoding UTF8
if ($config.InstallOffice -and $config.OfficeConfigXMLFile) {
Copy-Item -Path $config.OfficeConfigXMLFile -Destination $config.OfficePath -Force
$txtStatus.Text = "Office Configuration XML file copied successfully."
}
$txtStatus.Text = "Executing BuildFFUVM script with config file..."
# Prepare parameters for splatting
$buildParams = @{
ConfigFile = $configFilePath
}
if ($config.Verbose) {
$buildParams['Verbose'] = $true
}
& "$PSScriptRoot\BuildFFUVM.ps1" @buildParams
$txtStatus.Text = "FFU build completed successfully."
}
catch {
[System.Windows.MessageBox]::Show("An error occurred: $_", "Error", "OK", "Error")
$script:uiState.Controls.txtStatus.Text = "FFU build failed."
}
finally {
$script:uiState.Controls.pbOverallProgress.Visibility = 'Collapsed'
}
})
# Add handler for Remove button clicks
$window.Add_SourceInitialized({
$listView = $window.FindName('lstApplications')
$listView.AddHandler(
[System.Windows.Controls.Button]::ClickEvent,
[System.Windows.RoutedEventHandler] {
param($buttonSender, $clickEventArgs)
if ($clickEventArgs.OriginalSource -is [System.Windows.Controls.Button] -and $clickEventArgs.OriginalSource.Content -eq "Remove") {
Remove-Application -priority $clickEventArgs.OriginalSource.Tag -State $script:uiState
}
}
)
})
# Register cleanup to reclaim memory and revert LongPathsEnabled setting when the UI window closes
$window.Add_Closed({
# Revert LongPathsEnabled registry setting if it was changed by this script
if ($script:uiState.Flags.originalLongPathsValue -ne 1) {
# Only revert if we changed it from something other than 1
try {
$currentValue = Get-ItemPropertyValue -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -ErrorAction SilentlyContinue
if ($currentValue -eq 1) {
# Double-check it's still 1 before reverting
$revertValue = if ($null -eq $script:uiState.Flags.originalLongPathsValue) { 0 } else { $script:uiState.Flags.originalLongPathsValue } # Revert to original or 0 if it didn't exist
WriteLog "Reverting LongPathsEnabled registry key back to original value ($revertValue)."
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -Value $revertValue -Force
WriteLog "LongPathsEnabled reverted."
}
}
catch {
WriteLog "Error reverting LongPathsEnabled registry key: $($_.Exception.Message)."
}
}
# # Garbage collection
# [System.GC]::Collect()
# [System.GC]::WaitForPendingFinalizers()
})
[void]$window.ShowDialog()