From 1b0c0da67757a65c13902f60301e3768b046083f Mon Sep 17 00:00:00 2001 From: rbalsleyMSFT <53497092+rbalsleyMSFT@users.noreply.github.com> Date: Fri, 27 Jun 2025 12:51:51 -0700 Subject: [PATCH] Optimize driver download by checking for existing WIM files Refactors the driver download logic for all manufacturers to first check for the existence of a final `.wim` archive. If a WIM file is found, the download and processing for that model is skipped, significantly improving performance on subsequent runs. This change also resolves a potential type conversion error when processing driver mapping JSON files and corrects a minor typo in a log message. --- FFUDevelopment/BuildFFUVM.ps1 | 2 +- .../FFU.Common/FFU.Common.Drivers.psm1 | 5 ++- .../FFUUI.Core/FFUUI.Core.Drivers.Dell.psm1 | 19 +++++--- .../FFUUI.Core/FFUUI.Core.Drivers.HP.psm1 | 43 ++++++++++--------- .../FFUUI.Core/FFUUI.Core.Drivers.Lenovo.psm1 | 13 +++++- .../FFUUI.Core.Drivers.Microsoft.psm1 | 15 ++++--- 6 files changed, 63 insertions(+), 34 deletions(-) diff --git a/FFUDevelopment/BuildFFUVM.ps1 b/FFUDevelopment/BuildFFUVM.ps1 index ba42c86..a29fa2e 100644 --- a/FFUDevelopment/BuildFFUVM.ps1 +++ b/FFUDevelopment/BuildFFUVM.ps1 @@ -4978,7 +4978,7 @@ try { } else { #Use cached vhdx file - WriteLog 'Using cached VHDX file to speed up build proces' + WriteLog 'Using cached VHDX file to speed up build process' WriteLog "VHDX file is: $($cachedVHDXInfo.VhdxFileName)" Robocopy.exe $($VHDXCacheFolder) $($VMPath) $($cachedVHDXInfo.VhdxFileName) /E /COPY:DAT /R:5 /W:5 /J diff --git a/FFUDevelopment/FFU.Common/FFU.Common.Drivers.psm1 b/FFUDevelopment/FFU.Common/FFU.Common.Drivers.psm1 index 99b95e1..9f2e2c3 100644 --- a/FFUDevelopment/FFU.Common/FFU.Common.Drivers.psm1 +++ b/FFUDevelopment/FFU.Common/FFU.Common.Drivers.psm1 @@ -116,7 +116,10 @@ function Update-DriverMappingJson { $existingJson = Get-Content -Path $mappingFilePath -Raw | ConvertFrom-Json # Ensure it's a collection before adding to the list if ($existingJson -is [array]) { - $mappingList.AddRange($existingJson) + # Iterate through the array to avoid type conversion issues with AddRange + foreach ($item in $existingJson) { + $mappingList.Add($item) + } } else { $mappingList.Add($existingJson) diff --git a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.Dell.psm1 b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.Dell.psm1 index 201f742..ffe4af7 100644 --- a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.Dell.psm1 +++ b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.Dell.psm1 @@ -179,12 +179,16 @@ function Save-DellDriversTask { $driverRelativePath = Join-Path -Path $make -ChildPath $modelName # Relative path for the driver folder try { - # Define paths for Dell catalog. The catalog is assumed to be prepared by the calling function. - $dellDriversFolder = Join-Path -Path $DriversFolder -ChildPath "Dell" - $catalogBaseName = if ($WindowsRelease -le 11) { "CatalogPC" } else { "Catalog" } - $dellCatalogXML = Join-Path -Path $dellDriversFolder -ChildPath "$($catalogBaseName).xml" + # Check if WIM file or driver folder already exist + $wimFilePath = Join-Path -Path $makeDriversPath -ChildPath "$($modelName).wim" + if (Test-Path -Path $wimFilePath -PathType Leaf) { + $status = "Already downloaded (WIM)" + WriteLog "Driver WIM for '$modelName' already exists at '$wimFilePath'." + if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $modelName -Status $status } + $wimRelativePath = Join-Path -Path $make -ChildPath "$($modelName).wim" + return [PSCustomObject]@{ Model = $modelName; Status = $status; Success = $true; DriverPath = $wimRelativePath } + } - # 1. Check if drivers already exist for this model (final destination) if (Test-Path -Path $modelPath -PathType Container) { $folderSize = (Get-ChildItem -Path $modelPath -Recurse | Measure-Object -Property Length -Sum -ErrorAction SilentlyContinue).Sum if ($folderSize -gt 1MB) { @@ -198,6 +202,11 @@ function Save-DellDriversTask { } } + # Define paths for Dell catalog. The catalog is assumed to be prepared by the calling function. + $dellDriversFolder = Join-Path -Path $DriversFolder -ChildPath "Dell" + $catalogBaseName = if ($WindowsRelease -le 11) { "CatalogPC" } else { "Catalog" } + $dellCatalogXML = Join-Path -Path $dellDriversFolder -ChildPath "$($catalogBaseName).xml" + # 3. Parse the *EXISTING* XML and Find Drivers for *this specific model* $status = "Finding drivers..." if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $modelName -Status $status } diff --git a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.HP.psm1 b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.HP.psm1 index 0654eb8..ad26d51 100644 --- a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.HP.psm1 +++ b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.HP.psm1 @@ -121,6 +121,16 @@ function Save-HPDriversTask { if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $identifier -Status "Checking HP drivers for $modelName..." } + # Check if WIM file already exists + $wimFilePath = Join-Path -Path $hpDriversBaseFolder -ChildPath "$($identifier).wim" + if (Test-Path -Path $wimFilePath -PathType Leaf) { + $finalStatus = "Already downloaded (WIM)" + WriteLog "Driver WIM for '$identifier' already exists at '$wimFilePath'." + if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $identifier -Status $finalStatus } + $wimRelativePath = Join-Path -Path $make -ChildPath "$($identifier).wim" + return [PSCustomObject]@{ Identifier = $identifier; Status = $finalStatus; Success = $true; DriverPath = $wimRelativePath } + } + # Ensure the base HP folder exists if (-not (Test-Path -Path $hpDriversBaseFolder -PathType Container)) { try { @@ -142,25 +152,19 @@ function Save-HPDriversTask { if ($CompressToWim) { $wimFilePath = Join-Path -Path $hpDriversBaseFolder -ChildPath "$($identifier).wim" # WIM in base HP folder, next to model folder - - if (Test-Path -Path $wimFilePath -PathType Leaf) { - $finalStatus = "Already downloaded (WIM exists)" - WriteLog "WIM file $wimFilePath already exists for $identifier." + WriteLog "Attempting compression of existing folder '$modelSpecificFolder' to '$wimFilePath'." + if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $identifier -Status "Compressing existing HP drivers for $identifier..." } + try { + Compress-DriverFolderToWim -SourceFolderPath $modelSpecificFolder -DestinationWimPath $wimFilePath -WimName $identifier -WimDescription "Drivers for $identifier" -ErrorAction Stop + $finalStatus = "Already downloaded & Compressed" + WriteLog "Successfully compressed existing drivers for $identifier to $wimFilePath." + $driverRelativePath = Join-Path -Path $make -ChildPath "$($identifier).wim" } - else { - WriteLog "WIM file $wimFilePath not found for $identifier. Attempting compression of existing folder '$modelSpecificFolder'." - if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $identifier -Status "Compressing existing HP drivers for $identifier..." } - try { - Compress-DriverFolderToWim -SourceFolderPath $modelSpecificFolder -DestinationWimPath $wimFilePath -WimName $identifier -WimDescription "Drivers for $identifier" -ErrorAction Stop - $finalStatus = "Already downloaded & Compressed" - WriteLog "Successfully compressed existing drivers for $identifier to $wimFilePath." - } - catch { - $errMsgForLog = "Error compressing existing drivers for $($identifier): $($_.Exception.Message)" - WriteLog $errMsgForLog - $finalStatus = "Already downloaded (Compression failed: $($_.Exception.Message.Split([Environment]::NewLine)[0]))" - # $successState = false # Keep true if folder exists, compression is secondary - } + catch { + $errMsgForLog = "Error compressing existing drivers for $($identifier): $($_.Exception.Message)" + WriteLog $errMsgForLog + $finalStatus = "Already downloaded (Compression failed: $($_.Exception.Message.Split([Environment]::NewLine)[0]))" + # $successState = false # Keep true if folder exists, compression is secondary } } else { @@ -168,9 +172,6 @@ function Save-HPDriversTask { $finalStatus = "Already downloaded" } if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $identifier -Status $finalStatus } - if ($CompressToWim) { - $driverRelativePath = Join-Path -Path $make -ChildPath "$($identifier).wim" - } return [PSCustomObject]@{ Identifier = $identifier Status = $finalStatus diff --git a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.Lenovo.psm1 b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.Lenovo.psm1 index c0fbc60..d5e2b43 100644 --- a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.Lenovo.psm1 +++ b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.Lenovo.psm1 @@ -96,6 +96,17 @@ function Save-LenovoDriversTask { if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $identifier -Status "Checking..." } try { + # Check if WIM file or driver folder already exist + $sanitizedIdentifier = $identifier -replace '[\\/:"*?<>|]', '_' + $wimFilePath = Join-Path -Path $makeDriversPath -ChildPath "$($sanitizedIdentifier).wim" + if (Test-Path -Path $wimFilePath -PathType Leaf) { + $status = "Already downloaded (WIM)" + WriteLog "Driver WIM for '$identifier' already exists at '$wimFilePath'." + if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $identifier -Status $status } + $wimRelativePath = Join-Path -Path $make -ChildPath "$($sanitizedIdentifier).wim" + return [PSCustomObject]@{ Identifier = $identifier; Status = $status; Success = $true; DriverPath = $wimRelativePath } + } + # 1. Check if drivers already exist for this model (final destination) if (Test-Path -Path $modelPath -PathType Container) { $folderSize = (Get-ChildItem -Path $modelPath -Recurse | Measure-Object -Property Length -Sum -ErrorAction SilentlyContinue).Sum @@ -379,7 +390,7 @@ function Save-LenovoDriversTask { if ($CompressToWim) { $status = "Compressing..." if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $identifier -Status $status } - $wimFileName = "$($identifier).wim" # Use sanitized identifier for filename + $wimFileName = "$($sanitizedIdentifier).wim" # Use sanitized identifier for filename $destinationWimPath = Join-Path -Path $makeDriversPath -ChildPath $wimFileName $driverRelativePath = Join-Path -Path $make -ChildPath $wimFileName # Update relative path to the WIM file WriteLog "Compressing '$modelPath' to '$destinationWimPath'..." diff --git a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.Microsoft.psm1 b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.Microsoft.psm1 index 0586314..21ee24b 100644 --- a/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.Microsoft.psm1 +++ b/FFUDevelopment/FFUUI.Core/FFUUI.Core.Drivers.Microsoft.psm1 @@ -102,23 +102,28 @@ function Save-MicrosoftDriversTask { if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $modelName -Status "Checking..." } try { - # Check if drivers already exist for this model + # Check if WIM file or driver folder already exist $makeDriversPath = Join-Path -Path $DriversFolder -ChildPath $Make + $wimFilePath = Join-Path -Path $makeDriversPath -ChildPath "$($modelName).wim" + if (Test-Path -Path $wimFilePath -PathType Leaf) { + $status = "Already downloaded (WIM)" + WriteLog "Driver WIM for '$modelName' already exists at '$wimFilePath'." + if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $modelName -Status $status } + $wimRelativePath = Join-Path -Path $make -ChildPath "$($modelName).wim" + return [PSCustomObject]@{ Model = $modelName; Status = $status; Success = $true; DriverPath = $wimRelativePath } + } + $modelPath = Join-Path -Path $makeDriversPath -ChildPath $modelName if (Test-Path -Path $modelPath -PathType Container) { $folderSize = (Get-ChildItem -Path $modelPath -Recurse | Measure-Object -Property Length -Sum -ErrorAction SilentlyContinue).Sum if ($folderSize -gt 1MB) { $status = "Already downloaded" WriteLog "Drivers for '$modelName' already exist in '$modelPath'." - # Enqueue this status before returning if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $modelName -Status $status } - # Return success immediately return [PSCustomObject]@{ Model = $modelName; Status = $status; Success = $true; DriverPath = $driverRelativePath } } else { - # Status is not set to error here, just log and continue WriteLog "Driver folder '$modelPath' for '$modelName' exists but is empty or very small. Re-downloading." - # Allow the process to continue to re-download } }