diff --git a/FFUDevelopment/BuildFFUVM.ps1 b/FFUDevelopment/BuildFFUVM.ps1 index 1676068..22aadf7 100644 --- a/FFUDevelopment/BuildFFUVM.ps1 +++ b/FFUDevelopment/BuildFFUVM.ps1 @@ -39,6 +39,9 @@ When set to $true, will remove the drivers folder after the FFU has been capture .PARAMETER CompactOS When set to $true, will compact the OS when building the FFU. Default is $true. +.PARAMETER CompressDownloadedDriversToWim +When set to $true, compresses downloaded drivers into a WIM file. Default is $false. + .PARAMETER ConfigFile Path to a JSON file containing parameters to use for the script. Default is $null. @@ -72,6 +75,9 @@ Size of the virtual hard disk for the virtual machine. Default is a 30GB dynamic .PARAMETER DriversFolder Path to the drivers folder. Default is $FFUDevelopmentPath\Drivers. +.PARAMETER DriversJsonPath +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. @@ -114,12 +120,18 @@ Amount of memory to allocate for the virtual machine. Recommended to use 8GB if .PARAMETER Model Model of the device to download drivers. This is required if Make is set. +.PARAMETER OfficeConfigXMLFile +Path to a custom Office configuration XML file to use for installation. + .PARAMETER Optimize When set to $true, will optimize the FFU file. Default is $true. .PARAMETER OptionalFeatures Provide a semicolon-separated list of Windows optional features you want to include in the FFU (e.g., netfx3;TFTP). +.PARAMETER orchestrationPath +Path to the orchestration folder containing scripts that run inside the VM. Default is $FFUDevelopmentPath\Apps\Orchestration. + .PARAMETER PEDriversFolder Path to the folder containing drivers to be injected into the WinPE deployment media. Default is $FFUDevelopmentPath\PEDrivers. @@ -132,12 +144,12 @@ Product key for the Windows edition specified in WindowsSKU. This will overwrite .PARAMETER PromptExternalHardDiskMedia When set to $true, will prompt the user to confirm the use of media identified as External Hard Disk media via WMI class Win32_DiskDrive. Default is $true. -.PARAMETER RemoveFFU -When set to $true, will remove the FFU file from the $FFUDevelopmentPath\FFU folder after it has been copied to the USB drive. Default is $false. - .PARAMETER RemoveApps When set to $true, will remove the application content in the Apps folder after the FFU has been captured. Default is $true. +.PARAMETER RemoveFFU +When set to $true, will remove the FFU file from the $FFUDevelopmentPath\FFU folder after it has been copied to the USB drive. Default is $false. + .PARAMETER RemoveUpdates When set to $true, will remove the downloaded CU, MSRT, Defender, Edge, OneDrive, and .NET files downloaded. Default is $true. @@ -148,10 +160,10 @@ Name of the shared folder for FFU capture. The default is FFUCaptureShare. This When set to $true, the script will check for and install the latest Windows ADK and WinPE add-on if they are not already installed or up-to-date. Default is $true. .PARAMETER UpdateEdge -When set to $true, will download and install the latest Microsoft Edge for Windows 10/11. Default is $false. +When set to $true, will download and install the latest Microsoft Edge. Default is $false. .PARAMETER UpdateLatestCU -When set to $true, will download and install the latest cumulative update for Windows 10/11. Default is $false. +When set to $true, will download and install the latest cumulative update. Default is $false. .PARAMETER UpdateLatestDefender When set to $true, will download and install the latest Windows Defender definitions and Defender platform update. Default is $false. @@ -163,13 +175,16 @@ When set to $true, will download and install the latest microcode updates for ap When set to $true, will download and install the latest Windows Malicious Software Removal Tool. Default is $false. .PARAMETER UpdateLatestNet -When set to $true, will download and install the latest .NET Framework for Windows 10/11. Default is $false. +When set to $true, will download and install the latest .NET Framework. Default is $false. .PARAMETER UpdateOneDrive -When set to $true, will download and install the latest OneDrive for Windows 10/11 and install it as a per-machine installation instead of per-user. Default is $false. +When set to $true, will download and install the latest OneDrive and install it as a per-machine installation instead of per-user. Default is $false. .PARAMETER UpdatePreviewCU -When set to $true, will download and install the latest Preview cumulative update for Windows 10/11. Default is $false. +When set to $true, will download and install the latest Preview cumulative update. Default is $false. + +.PARAMETER UserAppListPath +Path to a JSON file containing a list of user-defined applications to install. Default is $FFUDevelopmentPath\Apps\UserAppList.json. .PARAMETER USBDriveList A hashtable containing USB drives from win32_diskdrive where: @@ -185,7 +200,7 @@ User agent string to use when downloading files. Username for accessing the shared folder. The default is ffu_user. The script will auto-create the account and password. When finished, it will remove the account. .PARAMETER VMHostIPAddress -IP address of the Hyper-V host for FFU capture. If $InstallApps is set to $true, this parameter must be configured. You must manually configure this. The script will not auto-detect your IP (depending on your network adapters, it may not find the correct IP). +IP address of the Hyper-V host for FFU capture. If $InstallApps is set to $true, this parameter must be configured. You must manually configure this, or use the UI to auto-detect. .PARAMETER VMLocation Default is $FFUDevelopmentPath\VM. This is the location of the VHDX that gets created where Windows will be installed to. @@ -405,7 +420,7 @@ param( [bool]$UpdateADK = $true ) $ProgressPreference = 'SilentlyContinue' -$version = '2505.1' +$version = '2507.1' # Remove any existing modules to avoid conflicts if (Get-Module -Name 'FFU.Common.Core' -ErrorAction SilentlyContinue) { diff --git a/FFUDevelopment/BuildFFUVM_UI.ps1 b/FFUDevelopment/BuildFFUVM_UI.ps1 index 4247de1..23b925a 100644 --- a/FFUDevelopment/BuildFFUVM_UI.ps1 +++ b/FFUDevelopment/BuildFFUVM_UI.ps1 @@ -1,3 +1,21 @@ +<# +.SYNOPSIS + Launches the FFU Development UI, a WPF application for configuring and running the FFU build process. +.DESCRIPTION + The BuildFFUVM_UI.ps1 script is the main entry point for the FFU Development user interface. It initializes and displays a WPF-based graphical interface defined in BuildFFUVM_UI.xaml. + + The script is responsible for: + - Initializing a global state object to manage UI controls, data, and application flags. + - Importing the required FFU.Common and FFUUI.Core modules which contain the business logic. + - Ensuring system prerequisites, such as PowerShell 7 and Long Path Support, are met. + - Loading the XAML window, initializing UI controls with default values, and registering all event handlers. + - Launching the core build script (BuildFFUVM.ps1) in a background job when the user initiates a build. + - Providing real-time feedback by monitoring the build log file and updating the UI's progress bar and log viewer. + - Handling cleanup operations, such as reverting system settings, when the application is closed. + + This script acts as the primary host for the UI, connecting the user interface with the underlying build and logic modules. +#> + [CmdletBinding()] [System.STAThread()] param() diff --git a/FFUDevelopment/FFU.Common/FFU.Common.Core.psm1 b/FFUDevelopment/FFU.Common/FFU.Common.Core.psm1 index 1e7441f..ccb2998 100644 --- a/FFUDevelopment/FFU.Common/FFU.Common.Core.psm1 +++ b/FFUDevelopment/FFU.Common/FFU.Common.Core.psm1 @@ -1,6 +1,12 @@ -# FFU.Common.Core.psm1 -# Contains common core functions like logging and process invocation. - +<# +.SYNOPSIS + Provides core, shared functions for logging, process execution, and resilient file transfers used across the FFU project. +.DESCRIPTION + This module is a central component of the FFU project, offering a set of robust, reusable functions. + It includes a centralized logging mechanism (WriteLog), a wrapper for running external processes with error handling (Invoke-Process), + a retry-aware BITS transfer function for reliable downloads (Start-BitsTransferWithRetry), and a progress reporting helper. + This module is designed to be imported by other scripts and modules within the project to ensure consistent behavior for common tasks. +#> # Script-scoped variable for the log file path $script:CommonCoreLogFilePath = $null # Mutex for log file access @@ -66,75 +72,6 @@ function WriteLog { } } -# Function to invoke external process -# function Invoke-Process { -# [CmdletBinding(SupportsShouldProcess)] -# param( -# [Parameter(Mandatory)] -# [ValidateNotNullOrEmpty()] -# [string]$FilePath, -# [Parameter()] -# [ValidateNotNullOrEmpty()] -# [string[]]$ArgumentList, -# [Parameter()] -# [ValidateNotNullOrEmpty()] -# [bool]$Wait = $true -# ) - -# $ErrorActionPreference = 'Stop' # Keep this local to the function - -# try { -# $stdOutTempFile = "$env:TEMP\$((New-Guid).Guid)" -# $stdErrTempFile = "$env:TEMP\$((New-Guid).Guid)" - -# $startProcessParams = @{ -# FilePath = $FilePath -# ArgumentList = $ArgumentList -# RedirectStandardError = $stdErrTempFile -# RedirectStandardOutput = $stdOutTempFile -# Wait = $Wait -# PassThru = $true -# NoNewWindow = $true -# } - -# # DEBUG -# # WriteLog "Running Command: $($startProcessParams.FilePath) $($startProcessParams.ArgumentList -join ' ')" - -# if ($PSCmdlet.ShouldProcess("Process [$($FilePath)]", "Run with args: [$($ArgumentList)]")) { -# $cmd = Start-Process @startProcessParams -# $cmdOutput = Get-Content -Path $stdOutTempFile -Raw -ErrorAction SilentlyContinue -# $cmdError = Get-Content -Path $stdErrTempFile -Raw -ErrorAction SilentlyContinue - -# if (-not [string]::IsNullOrWhiteSpace($cmdOutput)) { -# WriteLog "STDOUT from '$FilePath': $cmdOutput" -# } -# if (-not [string]::IsNullOrWhiteSpace($cmdError)) { -# WriteLog "STDERR from '$FilePath': $cmdError" -# } - -# if ($cmd.ExitCode -ne 0 -and $Wait) { -# $errorMessage = "Process '$FilePath' exited with code $($cmd.ExitCode)." -# if (-not [string]::IsNullOrWhiteSpace($cmdError)) { -# $errorMessage += " Error: $cmdError" -# } -# elseif (-not [string]::IsNullOrWhiteSpace($cmdOutput)) { -# $errorMessage += " Output: $cmdOutput" -# } -# throw $errorMessage.Trim() -# } -# } -# } -# catch { -# WriteLog "Error in Invoke-Process for '$FilePath': $($_.Exception.Message)" -# throw -# } -# finally { -# if (Test-Path $stdOutTempFile) { Remove-Item -Path $stdOutTempFile -Force -ErrorAction Ignore } -# if (Test-Path $stdErrTempFile) { Remove-Item -Path $stdErrTempFile -Force -ErrorAction Ignore } -# } -# return $cmd -# } - function Invoke-Process { [CmdletBinding(SupportsShouldProcess)] param @@ -257,7 +194,4 @@ function Set-Progress { WriteLog "[PROGRESS] $Percentage | $Message" } -# Suppress the default progress bar for a cleaner console output for any script importing this module. -# $ProgressPreference = 'SilentlyContinue' - Export-ModuleMember -Function * \ No newline at end of file diff --git a/FFUDevelopment/FFU.Common/FFU.Common.Drivers.psm1 b/FFUDevelopment/FFU.Common/FFU.Common.Drivers.psm1 index af33861..f0accca 100644 --- a/FFUDevelopment/FFU.Common/FFU.Common.Drivers.psm1 +++ b/FFUDevelopment/FFU.Common/FFU.Common.Drivers.psm1 @@ -1,10 +1,13 @@ -# FFU Common Drivers Module -# Contains shared functions related to driver handling. - -# -------------------------------------------------------------------------- -# SECTION: Driver Compression Function -# -------------------------------------------------------------------------- +<# +.SYNOPSIS + Provides common functions for driver management, including compression, mapping, and existence checks. +.DESCRIPTION + The FFU.Common.Drivers module contains a set of shared functions used across the FFU project for handling driver packages. + This includes compressing driver folders into WIM files for efficient storage and deployment, maintaining a JSON-based mapping + of downloaded drivers to their respective makes and models, and checking for the pre-existence of driver packages to avoid + redundant downloads. +#> function Compress-DriverFolderToWim { [CmdletBinding(SupportsShouldProcess)] param( diff --git a/FFUDevelopment/FFU.Common/FFU.Common.Parallel.psm1 b/FFUDevelopment/FFU.Common/FFU.Common.Parallel.psm1 index bf892b5..6808c5b 100644 --- a/FFUDevelopment/FFU.Common/FFU.Common.Parallel.psm1 +++ b/FFUDevelopment/FFU.Common/FFU.Common.Parallel.psm1 @@ -1,10 +1,57 @@ +<# +.SYNOPSIS + Manages and executes multiple background tasks in parallel, with support for updating a WPF UI with progress. +.DESCRIPTION + This function provides a generic framework for running tasks in parallel using PowerShell's ForEach-Object -Parallel. + It is designed to process an array of items, executing a specific task for each one. It can operate in two modes: UI mode and non-UI mode. + + In UI mode, it updates a specified ListView control in a WPF window with the status of each item as it's being processed + (e.g., Queued, Downloading, Completed, Error). It uses a dispatcher to ensure UI updates are thread-safe. + + In non-UI mode, it runs the tasks and logs the status to the FFUDevelopment.log file. + + The function determines the task to run via the -TaskType parameter and passes necessary arguments using -TaskArguments. + It handles module imports and log file setup within each parallel runspace to ensure tasks have the necessary dependencies and logging capabilities. +.PARAMETER ItemsToProcess + An array of objects, where each object represents an item to be processed by a parallel task. This is a mandatory parameter. +.PARAMETER ListViewControl + (UI Mode) The WPF ListView control that the function will update with the status of each item. Defaults to $null. +.PARAMETER IdentifierProperty + The name of the property on the item objects that serves as a unique identifier (e.g., 'Name', 'Id'). + This is used to find and update the correct row in the ListView. +.PARAMETER StatusProperty + The name of the property on the item objects that holds the status string. This property will be updated with progress messages. +.PARAMETER TaskType + A string specifying which task to execute for each item. This is mandatory. + Valid values are: + - 'WingetDownload': Downloads a Winget application. + - 'CopyBYO': Copies a user-provided application. + - 'DownloadDriverByMake': Downloads drivers for a specific manufacturer. +.PARAMETER TaskArguments + A hashtable containing arguments required by the specific task being run (e.g., paths, API keys, configuration settings). +.PARAMETER CompletedStatusText + The status text to display when an item is processed successfully. +.PARAMETER ErrorStatusPrefix + A prefix for status messages when an error occurs. +.PARAMETER WindowObject + (UI Mode) The main WPF Window object, used to access the UI dispatcher for safe UI updates from background threads. +.PARAMETER MainThreadLogPath + The file path for the log file that should be used by all parallel threads. This ensures consistent logging. +.PARAMETER ThrottleLimit + The maximum number of parallel jobs to run concurrently. The default is 5. +.NOTES + This function relies on ForEach-Object -Parallel, which was introduced in PowerShell 7. + When running in UI mode, both -WindowObject and -ListViewControl must be provided. + The function dynamically imports required modules ('FFU.Common' and 'FFUUI.Core') into each parallel runspace. + It uses a concurrent queue to manage intermediate progress updates from threads to the main UI thread, preventing UI blocking and providing more granular feedback. +#> function Invoke-ParallelProcessing { [CmdletBinding()] param( [Parameter(Mandatory)] [array]$ItemsToProcess, [Parameter(Mandatory = $false)] - [object]$ListViewControl = $null, # Changed type to [object] + [object]$ListViewControl = $null, [Parameter(Mandatory = $false)] [string]$IdentifierProperty = 'Identifier', [Parameter(Mandatory = $false)] @@ -19,9 +66,9 @@ function Invoke-ParallelProcessing { [Parameter(Mandatory = $false)] [string]$ErrorStatusPrefix = "Error: ", [Parameter(Mandatory = $false)] - [object]$WindowObject = $null, # Changed type to [object] + [object]$WindowObject = $null, [Parameter(Mandatory = $false)] - [string]$MainThreadLogPath = $null, # New parameter for the log path + [string]$MainThreadLogPath = $null, [Parameter(Mandatory = $false)] [int]$ThrottleLimit = 5 ) @@ -60,11 +107,9 @@ function Invoke-ParallelProcessing { $jobScopeVariables = $TaskArguments.Clone() $jobScopeVariables['_commonModulePath'] = $commonModulePathForJob $jobScopeVariables['_uiCoreModulePath'] = $uiCoreModulePathForJob - $jobScopeVariables['_currentLogFilePathForJob'] = $currentLogFilePathForJob # Pass the determined log path + $jobScopeVariables['_currentLogFilePathForJob'] = $currentLogFilePathForJob $jobScopeVariables['_progressQueue'] = $progressQueue - # The $TaskScriptBlock parameter is already a local variable in this scope - # Initial UI update needs to happen *before* starting the jobs # Update all items to a static "Processing..." status if ($isUiMode) { @@ -89,13 +134,9 @@ function Invoke-ParallelProcessing { # $jobScopeVariables and $TaskType are local here # Inside the -Parallel scriptblock, we access them with $using: $jobs = $ItemsToProcess | ForEach-Object -Parallel { - # Access the current item via pipeline variable $_ $currentItem = $_ - # Access the combined arguments hashtable from the calling scope using $using: $localJobArgs = $using:jobScopeVariables - # Access the task type string from the calling scope using $using: $localTaskType = $using:TaskType - # Access the progress queue using $using: $localProgressQueue = $localJobArgs['_progressQueue'] # Initialize result hashtable @@ -242,9 +283,7 @@ function Invoke-ParallelProcessing { WriteLog $nullTaskResultMessage $resultStatus = $nullTaskResultMessage $resultCode = 1 - # $resultIdentifier is already set } - # If it was an unsupported Make, $resultStatus and $resultCode are already set from the 'default' case. } Default { # This handles unknown $localTaskType values @@ -261,7 +300,6 @@ function Invoke-ParallelProcessing { } } catch { - # Catch errors within the parallel task execution $resultStatus = "Error: $($_.Exception.Message)" $resultCode = 1 # Try to get an identifier @@ -272,7 +310,6 @@ function Invoke-ParallelProcessing { $resultIdentifier = "UnknownItemOnError" } WriteLog "Exception during parallel task '$localTaskType' for item '$resultIdentifier': $($_.Exception.ToString())" - # Enqueue the error status from the catch block $localProgressQueue.Enqueue(@{ Identifier = $resultIdentifier; Status = $resultStatus }) } @@ -284,7 +321,7 @@ function Invoke-ParallelProcessing { # Return a consistent hashtable structure (final result) return @{ Identifier = $resultIdentifier - Status = $resultStatus # Return the final status + Status = $resultStatus ResultCode = $resultCode DriverPath = $driverPathValue } @@ -292,7 +329,6 @@ function Invoke-ParallelProcessing { } -ThrottleLimit $ThrottleLimit -AsJob } catch { - # Catch errors during the *creation* of the parallel jobs (e.g., module loading in main thread failed) WriteLog "Error initiating ForEach-Object -Parallel: $($_.Exception.Message)" # Update all items to show a general startup error $errorStatus = "$ErrorStatusPrefix Failed to start processing" @@ -302,7 +338,6 @@ function Invoke-ParallelProcessing { Update-ListViewItemStatus -WindowObject $WindowObject -ListView $ListViewControl -IdentifierProperty $IdentifierProperty -IdentifierValue $identifier -StatusProperty $StatusProperty -StatusValue $errorStatus # Pass $WindowObject }) } - # Exit the function as processing cannot proceed return } @@ -334,7 +369,6 @@ function Invoke-ParallelProcessing { } $intermediateStatus = $statusUpdate.Status if ($isUiMode) { - # Use the new $isUiMode flag # Update the UI with the intermediate status try { WriteLog "Dispatching INTERMEDIATE status for '$intermediateIdentifier': '$intermediateStatus'" @@ -361,7 +395,7 @@ function Invoke-ParallelProcessing { $jobHandled = $false if ($completedJob.State -eq 'Failed') { $jobHandled = $true - $finalIdentifier = "UnknownJob" # Placeholder + $finalIdentifier = "UnknownJob" WriteLog "Job $($completedJob.Id) failed: $($completedJob.Error)" $finalStatus = "$ErrorStatusPrefix Job Failed" $finalResultCode = 1 @@ -438,12 +472,11 @@ function Invoke-ParallelProcessing { # Remove the completed/failed job from the list and clean it up $jobs = $jobs | Where-Object { $_.Id -ne $completedJob.Id } Remove-Job -Job $completedJob -Force -ErrorAction SilentlyContinue - } # End foreach completedJob - } # End if ($completedJobs) + } + } # 3. Allow UI events to process and sleep briefly if ($isUiMode) { - # Use the new $isUiMode flag # Only sleep if jobs are still running AND the queue is empty (to avoid delaying UI updates) if ($jobs.Count -gt 0 -and $progressQueue.IsEmpty) { $WindowObject.Dispatcher.Invoke([System.Windows.Threading.DispatcherPriority]::Background, [action] { }) | Out-Null @@ -460,9 +493,8 @@ function Invoke-ParallelProcessing { Start-Sleep -Milliseconds 100 } } - # If jobs are done AND queue is empty, the loop condition will terminate - } # End while ($jobs.Count -gt 0 -or -not $progressQueue.IsEmpty) + } # Final cleanup of any remaining jobs (shouldn't be necessary with this loop logic, but good practice) if ($jobs.Count -gt 0) { @@ -471,7 +503,6 @@ function Invoke-ParallelProcessing { } if ($isUiMode) { - # Use the new $isUiMode flag WriteLog "Invoke-ParallelProcessing finished for ListView '$($ListViewControl.Name)'." # Final overall progress update $WindowObject.Dispatcher.Invoke([System.Windows.Threading.DispatcherPriority]::Background, [Action] { diff --git a/FFUDevelopment/FFU.Common/FFU.Common.Winget.psm1 b/FFUDevelopment/FFU.Common/FFU.Common.Winget.psm1 index 6654b80..892eb7e 100644 --- a/FFUDevelopment/FFU.Common/FFU.Common.Winget.psm1 +++ b/FFUDevelopment/FFU.Common/FFU.Common.Winget.psm1 @@ -1,6 +1,12 @@ -# # Import the common core module for logging -# Import-Module "$PSScriptRoot\FFU.Common.Core.psm1" +<# +.SYNOPSIS + Provides functions for interacting with WinGet and the Microsoft Store to find, download, and configure applications. +.DESCRIPTION + This module contains a set of functions designed to automate application management using the WinGet package manager and the Microsoft Store. + It supports checking for and installing WinGet, downloading applications, handling different application types (Win32 and UWP), and generating silent installation commands for Win32 applications. + This module is used by both the build script (BuildFFUVM.ps1) and the UI (BuildFFUVM_UI.ps1) to manage application downloads and configuration. +#> function Get-Application { [CmdletBinding()] param ( diff --git a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Applications.psm1 b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Applications.psm1 index 21393d5..a660cc8 100644 --- a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Applications.psm1 +++ b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Applications.psm1 @@ -1,5 +1,9 @@ -# FFU UI Core Applications Module -# Contains UI-layer logic for the "Bring Your Own Apps" and related features. +<# +.SYNOPSIS + Manages the UI business logic for the "Applications" tab, including "Bring Your Own (BYO) Applications" and "Apps Script Variables". +.DESCRIPTION + This module contains all the functions that power the "Applications" tab in the BuildFFUVM_UI. It handles user interactions for managing custom application lists (BYO Apps), such as adding, removing, reordering, and saving/loading the list from a JSON file (UserAppList.json). It also includes the logic for copying the application source files to the designated staging directory in parallel. Additionally, it manages the UI for creating and removing key-value pairs for the AppsScriptVariables.json file, which allows for custom parameterization of user-provided scripts. +#> # Function to update the enabled state of the Copy Apps button function Update-CopyButtonState { diff --git a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Config.psm1 b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Config.psm1 index b12a99e..821b396 100644 --- a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Config.psm1 +++ b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Config.psm1 @@ -1,6 +1,9 @@ -# FFU UI Core Configuration Module -# Contains functions for loading and saving UI configuration. - +<# +.SYNOPSIS + Contains functions for loading and saving UI configuration. +.DESCRIPTION + This module provides the core logic for loading and saving the UI configuration. It includes functions to gather settings from the various UI controls, save them to a JSON file, and load settings from a JSON file to populate the UI. This allows users to persist their build configurations and easily switch between different setups. +#> function Get-UIConfig { param( [Parameter(Mandatory = $true)] diff --git a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.Dell.psm1 b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.Dell.psm1 index 6be2f64..1127145 100644 --- a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.Dell.psm1 +++ b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.Dell.psm1 @@ -1,3 +1,10 @@ +<# +.SYNOPSIS + Provides functions for discovering, downloading, and processing Dell device drivers. +.DESCRIPTION + This module contains the logic specific to handling Dell drivers for the FFU Builder UI. It includes functions to parse Dell's large XML driver catalog to retrieve a list of supported models (Get-DellDriversModelList). It also provides a parallel-capable task function (Save-DellDriversTask) that finds, downloads, extracts, and optionally compresses all the latest driver packages for a specified Dell model and operating system. +#> + # Function to get the list of Dell models from the catalog using XML streaming function Get-DellDriversModelList { [CmdletBinding()] diff --git a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.HP.psm1 b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.HP.psm1 index 8640a4b..d0aad83 100644 --- a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.HP.psm1 +++ b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.HP.psm1 @@ -1,3 +1,15 @@ +<# +.SYNOPSIS + Provides functions to retrieve HP model lists and download corresponding driver packs. +.DESCRIPTION + This module contains the logic specific to handling HP drivers for the FFU Builder UI. It includes functions to: + - Download and parse the HP PlatformList.xml to generate a list of supported HP computer models. + - For a selected model, find the most appropriate driver pack based on the specified Windows release and version, with intelligent fallback logic. + - Download the driver pack, extract all individual driver installers, and then extract the driver files from each installer. + - Optionally, compress the final extracted drivers into a single WIM file for easier deployment. + These functions are designed to be called by the main UI logic, often in parallel, to efficiently manage driver acquisition. +#> + # Function to get the list of HP models from the PlatformList.xml function Get-HPDriversModelList { [CmdletBinding()] diff --git a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.Lenovo.psm1 b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.Lenovo.psm1 index 3924faf..c3de3b6 100644 --- a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.Lenovo.psm1 +++ b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.Lenovo.psm1 @@ -1,3 +1,10 @@ +<# +.SYNOPSIS + Provides functions for discovering, downloading, and processing Lenovo drivers. +.DESCRIPTION + This module contains the logic specific to handling Lenovo drivers for the FFU Builder UI. It includes functions to query the Lenovo PSREF (Product Specification Reference) API to find and list available system models based on user search terms. It also provides the core background task for downloading all relevant driver packages for a selected model and Windows release. The download process involves parsing XML catalogs, downloading individual driver executables, silently extracting their contents, and organizing them into a structured folder. The module includes robust error handling, long path mitigation by using temporary extraction locations, and an option to compress the final driver set into a WIM archive. +#> + # Function to get the list of Lenovo models using the PSREF API function Get-LenovoDriversModelList { [CmdletBinding()] diff --git a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.Microsoft.psm1 b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.Microsoft.psm1 index 86edf20..6a937d2 100644 --- a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.Microsoft.psm1 +++ b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.Microsoft.psm1 @@ -1,3 +1,10 @@ +<# +.SYNOPSIS + Provides functions for discovering, downloading, and processing Microsoft Surface device drivers. +.DESCRIPTION + This module contains the logic specific to handling Microsoft Surface drivers for the FFU UI. It includes a function to scrape the official Microsoft support website to build a list of available Surface models and their driver download pages. It also provides a robust, parallel-capable function to download the correct driver package (MSI or ZIP) based on the selected Windows release, extract its contents, and optionally compress them into a WIM archive. The download process includes logic to handle MSI installer mutexes to prevent conflicts during parallel execution. +#> + # Function to get the list of Microsoft Surface models function Get-MicrosoftDriversModelList { [CmdletBinding()] diff --git a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.psm1 b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.psm1 index 74f17b1..a160eb4 100644 --- a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.psm1 +++ b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.psm1 @@ -1,3 +1,10 @@ +<# +.SYNOPSIS + Provides functions for managing and downloading hardware drivers in the FFU Builder UI. +.DESCRIPTION + This module contains all the business logic for the 'Drivers' tab in the FFU Builder UI. It handles fetching driver model lists from various manufacturers (Microsoft, Dell, HP, Lenovo), displaying and filtering them in the UI, and managing the selection state. It also includes functions to import and export driver selections to a JSON file (Drivers.json) and to orchestrate the parallel download of selected driver packages using the common parallel processing module. +#> + # Helper function to get models for a selected Make and standardize them function Get-ModelsForMake { param( diff --git a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Handlers.psm1 b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Handlers.psm1 index a25683a..eb5b111 100644 --- a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Handlers.psm1 +++ b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Handlers.psm1 @@ -1,3 +1,10 @@ +<# +.SYNOPSIS + Contains the function for registering all WPF UI event handlers for the FFU Builder application. +.DESCRIPTION + 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 Register-EventHandlers { param([PSCustomObject]$State) WriteLog "Registering UI event handlers..." diff --git a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Initialize.psm1 b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Initialize.psm1 index a63a1a3..a704732 100644 --- a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Initialize.psm1 +++ b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Initialize.psm1 @@ -1,3 +1,18 @@ +<# +.SYNOPSIS + Initializes the user interface for the BuildFFUVM_UI application. + +.DESCRIPTION + This script module contains functions responsible for initializing the WPF user interface. + It handles several key tasks: + - Caching references to all UI controls for efficient access. + - Populating UI elements like combo boxes with data (e.g., Hyper-V switches). + - Setting default values for all controls based on configuration or predefined settings. + - Dynamically creating and configuring complex UI components, such as sortable/selectable GridView columns and feature selection grids. + + This module is critical for setting up the initial state of the application window when it first loads. +#> + function Initialize-UIControls { param([PSCustomObject]$State) WriteLog "Initializing UI control references..." diff --git a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Shared.psm1 b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Shared.psm1 index f5baebd..561b933 100644 --- a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Shared.psm1 +++ b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Shared.psm1 @@ -1,3 +1,10 @@ +<# +.SYNOPSIS + Provides a collection of shared helper functions for manipulating WPF UI controls, handling asynchronous updates, and managing common UI interactions. +.DESCRIPTION + This module contains a variety of reusable functions designed to support the FFU Builder UI. It includes utilities for managing ListView controls, such as sorting, reordering items, and handling 'Select All' functionality. It also provides thread-safe mechanisms for updating the UI from background tasks, wrappers for modern and classic file/folder dialogs, and generic functions for clearing UI content. These shared functions help to reduce code duplication and ensure consistent behavior across different parts of the application. +#> + # Function to update priorities sequentially in a ListView function Update-ListViewPriorities { param( @@ -96,9 +103,9 @@ function Update-ListViewItemStatus { [CmdletBinding()] param( [Parameter(Mandatory)] - [object]$WindowObject, # Changed type to [object] + [object]$WindowObject, [Parameter(Mandatory)] - [object]$ListView, # Changed type to [object] + [object]$ListView, [Parameter(Mandatory)] [string]$IdentifierProperty, [Parameter(Mandatory)] @@ -135,7 +142,7 @@ function Update-ListViewItemStatus { catch { WriteLog "Update-ListViewItemStatus: Error updating ListView: $($_.Exception.Message)" } - } # End of if ($WindowObject -is [System.Windows.Window]...) + } else { # Log if called in non-UI mode or with incorrect types (should not happen if Invoke-ParallelProcessing $isUiMode is correct) WriteLog "Update-ListViewItemStatus: Skipped UI update for $IdentifierValue due to non-UI mode or incorrect object types." @@ -147,7 +154,7 @@ function Update-OverallProgress { [CmdletBinding()] param( [Parameter(Mandatory)] - [object]$WindowObject, # Changed type to [object] + [object]$WindowObject, [Parameter(Mandatory)] [int]$CompletedCount, [Parameter(Mandatory)] @@ -193,7 +200,7 @@ function Update-OverallProgress { catch { WriteLog "Update-OverallProgress: Error updating progress: $($_.Exception.Message)" } - } # End of if ($WindowObject -is [System.Windows.Window]) + } else { # Log if called in non-UI mode or with incorrect types WriteLog "Update-OverallProgress: Skipped UI update ($StatusText) due to non-UI mode or incorrect WindowObject type." @@ -242,7 +249,6 @@ function Add-SortableColumn { $checkBoxFactory.AddHandler([System.Windows.Controls.CheckBox]::ClickEvent, [System.Windows.RoutedEventHandler] { param($eventSourceLocal, $eventArgsLocal) - # Sync logic would be needed here if this column had a header checkbox }) $gridFactory.AppendChild($checkBoxFactory) $cellTemplate.VisualTree = $gridFactory @@ -314,7 +320,7 @@ function Add-SelectableGridViewColumn { # MODIFICATION: Store the actual ListView object in the header's Tag $headerTagObject = [PSCustomObject]@{ PropertyName = $IsSelectedPropertyName - ListViewControl = $ListView # Store the object itself + ListViewControl = $ListView } $headerCheckBox.Tag = $headerTagObject @@ -322,7 +328,7 @@ function Add-SelectableGridViewColumn { param($senderCheckBoxLocal, $eventArgsCheckedLocal) $tagData = $senderCheckBoxLocal.Tag $localPropertyName = $tagData.PropertyName - $actualListView = $tagData.ListViewControl # Get the control directly from the tag + $actualListView = $tagData.ListViewControl $collectionToUpdate = if ($null -ne $actualListView.ItemsSource) { $actualListView.ItemsSource } else { $actualListView.Items } if ($null -ne $collectionToUpdate) { @@ -336,7 +342,7 @@ function Add-SelectableGridViewColumn { if ($senderCheckBoxLocal.IsChecked -eq $false) { $tagData = $senderCheckBoxLocal.Tag $localPropertyName = $tagData.PropertyName - $actualListView = $tagData.ListViewControl # Get the control directly from the tag + $actualListView = $tagData.ListViewControl $collectionToUpdate = if ($null -ne $actualListView.ItemsSource) { $actualListView.ItemsSource } else { $actualListView.Items } if ($null -ne $collectionToUpdate) { @@ -366,7 +372,7 @@ function Add-SelectableGridViewColumn { # MODIFICATION: Store the actual ListView object in the item checkbox's Tag $tagObject = [PSCustomObject]@{ HeaderCheckboxKeyName = $HeaderCheckBoxKeyName - ListViewControl = $ListView # Store the object itself + ListViewControl = $ListView } $checkBoxFactory.SetValue([System.Windows.FrameworkElement]::TagProperty, $tagObject) @@ -376,7 +382,7 @@ function Add-SelectableGridViewColumn { $tagData = $itemCheckBox.Tag $headerCheckboxKeyFromTag = $tagData.HeaderCheckboxKeyName - $targetListView = $tagData.ListViewControl # Get the control directly from the tag + $targetListView = $tagData.ListViewControl # Get the state from the window tag $window = [System.Windows.Window]::GetWindow($targetListView) diff --git a/FFUDevelopment/FFUUI.Core/FFUUI.Core.WindowsSettings.psm1 b/FFUDevelopment/FFUUI.Core/FFUUI.Core.WindowsSettings.psm1 index 42cbc6e..d174f46 100644 --- a/FFUDevelopment/FFUUI.Core/FFUUI.Core.WindowsSettings.psm1 +++ b/FFUDevelopment/FFUUI.Core/FFUUI.Core.WindowsSettings.psm1 @@ -1,5 +1,9 @@ -# FFU UI Core Windows Settings Logic Module -# Contains UI helper functions, data retrieval, and core processing logic for the Windows Settings tab. +<# +.SYNOPSIS + Manages the business logic for the 'Windows Settings' tab in the FFU Builder UI. +.DESCRIPTION + This module contains all the functions and data required to populate and manage the controls on the 'Windows Settings' tab. It handles dynamic updates for Windows Release, Version, SKU, and Architecture ComboBoxes based on user input, such as specifying an ISO path. It also includes logic for populating available languages, media types, and the grid of optional Windows features. +#> # -------------------------------------------------------------------------- # SECTION: Module Variables (Static Data) @@ -170,8 +174,6 @@ $script:ltscGenericSKUs = @( # For LTSC 2019, 2021, 2024 $script:iotLtscSKUs = @( 'IoT Enterprise LTSC', 'IoT Enterprise N LTSC' - # Note: IoT SKUs are often specialized and might have different edition IDs. - # This list is a general representation. Actual ISOs might be needed for specific IoT LTSC editions. ) # Map Windows Release Values to their corresponding SKU lists diff --git a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Winget.psm1 b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Winget.psm1 index c5449c9..29e19de 100644 --- a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Winget.psm1 +++ b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Winget.psm1 @@ -1,9 +1,9 @@ -# FFU UI Core Logic Module - Winget Functionality -# Contains UI-layer logic for the Winget functionality in the "Applications" tab. - -# ----------------------------------------------------------------------------- -# SECTION: Winget UI Functions (Moved from BuildFFUVM_UI.ps1) -# ----------------------------------------------------------------------------- +<# +.SYNOPSIS + Manages all Winget-related functionality for the 'Applications' tab in the FFU Builder UI. +.DESCRIPTION + This module provides the business logic for interacting with Winget from the FFU Builder UI. It includes functions for searching for packages, importing and exporting application lists, checking for and installing necessary Winget components (CLI and PowerShell module), and managing the parallel download of selected applications. It works in conjunction with FFU.Common.Winget for lower-level operations and FFU.Common.Parallel for managing concurrent downloads. +#> # Function to search for Winget apps function Search-WingetApps { diff --git a/FFUDevelopment/FFUUI.Core/FFUUI.Core.psm1 b/FFUDevelopment/FFUUI.Core/FFUUI.Core.psm1 index d74a39c..bb57081 100644 --- a/FFUDevelopment/FFUUI.Core/FFUUI.Core.psm1 +++ b/FFUDevelopment/FFUUI.Core/FFUUI.Core.psm1 @@ -1,5 +1,9 @@ -# FFU UI Core Logic Module -# Contains non-UI specific helper functions, data retrieval, and core processing logic. +<# +.SYNOPSIS + Core logic module for the FFU Builder UI, providing helper functions, data retrieval, and UI state management. +.DESCRIPTION + This module serves as the central logic hub for the FFU Builder UI. It contains functions for retrieving system information (like Hyper-V switches and USB drives), providing default application settings, and dynamically managing the visibility and state of various UI controls across different tabs based on user selections. It orchestrates the interactions between different parts of the UI to ensure a consistent and logical user experience. +#> # -------------------------------------------------------------------------- # SECTION: Module Variables (Static Data & State)