Refactor driver cleanup logic into reusable helper function

Extracts duplicate folder removal code across multiple driver modules (Dell, HP, Lenovo, Microsoft) into a centralized `Remove-DriverModelFolder` helper function. This new utility includes safety checks to prevent accidental deletion of the drivers root directory or paths outside the drivers folder hierarchy.

Also moves model path construction in the Microsoft driver module earlier in the function to ensure consistent path handling before any operations that might fail.

Benefits improved maintainability, reduces code duplication, and adds protective safeguards for destructive operations during error handling.
This commit is contained in:
rbalsleyMSFT
2025-11-20 17:05:31 -08:00
parent 7d36253668
commit 3d1a586c73
5 changed files with 56 additions and 16 deletions
@@ -362,6 +362,7 @@ function Save-DellDriversTask {
catch { catch {
$errorStatus = "Error: $($_.Exception.Message)" $errorStatus = "Error: $($_.Exception.Message)"
WriteLog "Save-DellDriversTask error for $($modelDisplay): $($_.Exception.ToString())" WriteLog "Save-DellDriversTask error for $($modelDisplay): $($_.Exception.ToString())"
Remove-DriverModelFolder -DriversFolder $DriversFolder -TargetFolder $modelPath -Description $modelDisplay
if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $modelDisplay -Status $errorStatus } if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $modelDisplay -Status $errorStatus }
return [pscustomobject]@{ Model = $modelDisplay; Status = $errorStatus; Success = $false; DriverPath = $null } return [pscustomobject]@{ Model = $modelDisplay; Status = $errorStatus; Success = $false; DriverPath = $null }
} }
@@ -426,10 +426,7 @@ function Save-HPDriversTask {
$finalStatus = "Error: $($_.Exception.Message.Split([Environment]::NewLine)[0])" $finalStatus = "Error: $($_.Exception.Message.Split([Environment]::NewLine)[0])"
$successState = $false $successState = $false
$driverRelativePath = $null # Ensure path is null on error $driverRelativePath = $null # Ensure path is null on error
if (Test-Path -Path $modelSpecificFolder -PathType Container) { Remove-DriverModelFolder -DriversFolder $DriversFolder -TargetFolder $modelSpecificFolder -Description $identifier
WriteLog "Attempting to remove partially created folder $modelSpecificFolder due to error."
Remove-Item -Path $modelSpecificFolder -Recurse -Force -ErrorAction SilentlyContinue
}
} }
if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $identifier -Status $finalStatus } if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $identifier -Status $finalStatus }
@@ -459,6 +459,7 @@ function Save-LenovoDriversTask {
$status = "Error: $($_.Exception.Message)" $status = "Error: $($_.Exception.Message)"
WriteLog "Error saving Lenovo drivers for '$identifier': $($_.Exception.ToString())" WriteLog "Error saving Lenovo drivers for '$identifier': $($_.Exception.ToString())"
$success = $false $success = $false
Remove-DriverModelFolder -DriversFolder $DriversFolder -TargetFolder $modelPath -Description $identifier
if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $identifier -Status $status } if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $identifier -Status $status }
return [PSCustomObject]@{ Identifier = $identifier; Status = $status; Success = $success; DriverPath = $null } return [PSCustomObject]@{ Identifier = $identifier; Status = $status; Success = $success; DriverPath = $null }
} }
@@ -106,6 +106,10 @@ function Save-MicrosoftDriversTask {
$driverRelativePath = Join-Path -Path $make -ChildPath $modelName # Relative path for the driver folder $driverRelativePath = Join-Path -Path $make -ChildPath $modelName # Relative path for the driver folder
$status = "Getting download link..." # Initial local status $status = "Getting download link..." # Initial local status
$success = $false $success = $false
$sanitizedModelName = ConvertTo-SafeName -Name $modelName
if ($sanitizedModelName -ne $modelName) { WriteLog "Sanitized model name: '$modelName' -> '$sanitizedModelName'" }
$makeDriversPath = Join-Path -Path $DriversFolder -ChildPath $make
$modelPath = Join-Path -Path $makeDriversPath -ChildPath $sanitizedModelName
# Initial status update # Initial status update
if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $modelName -Status "Checking..." } if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $modelName -Status "Checking..." }
@@ -235,10 +239,6 @@ function Save-MicrosoftDriversTask {
WriteLog "Creating Drivers folder: $DriversFolder" WriteLog "Creating Drivers folder: $DriversFolder"
New-Item -Path $DriversFolder -ItemType Directory -Force | Out-Null New-Item -Path $DriversFolder -ItemType Directory -Force | Out-Null
} }
$sanitizedModelName = ConvertTo-SafeName -Name $modelName
if ($sanitizedModelName -ne $modelName) { WriteLog "Sanitized model name: '$modelName' -> '$sanitizedModelName'" }
$makeDriversPath = Join-Path -Path $DriversFolder -ChildPath $Make
$modelPath = Join-Path -Path $makeDriversPath -ChildPath $sanitizedModelName
if (-Not (Test-Path -Path $modelPath)) { if (-Not (Test-Path -Path $modelPath)) {
WriteLog "Creating model folder: $modelPath" WriteLog "Creating model folder: $modelPath"
New-Item -Path $modelPath -ItemType Directory -Force | Out-Null New-Item -Path $modelPath -ItemType Directory -Force | Out-Null
@@ -422,6 +422,7 @@ function Save-MicrosoftDriversTask {
$status = "Error: $($_.Exception.Message.Split('.')[0])" # Shorten error message $status = "Error: $($_.Exception.Message.Split('.')[0])" # Shorten error message
WriteLog "Error saving Microsoft drivers for $($modelName): $($_.Exception.Message)" WriteLog "Error saving Microsoft drivers for $($modelName): $($_.Exception.Message)"
$success = $false $success = $false
Remove-DriverModelFolder -DriversFolder $DriversFolder -TargetFolder $modelPath -Description $modelName
# Enqueue the error status before returning # Enqueue the error status before returning
if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $modelName -Status $status } if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $modelName -Status $status }
# Ensure return object is created even on error # Ensure return object is created even on error
@@ -97,10 +97,50 @@ function Convert-DriverItemToJsonModel {
return $null return $null
} }
} }
} }
# Helper function to get models for a selected Make and standardize them function Remove-DriverModelFolder {
function Get-ModelsForMake { param(
[Parameter(Mandatory = $true)]
[string]$DriversFolder,
[Parameter(Mandatory = $true)]
[string]$TargetFolder,
[string]$Description
)
if ([string]::IsNullOrWhiteSpace($DriversFolder) -or [string]::IsNullOrWhiteSpace($TargetFolder)) {
return
}
try {
if (-not (Test-Path -Path $TargetFolder -PathType Container)) {
return
}
$driversRoot = [System.IO.Path]::GetFullPath((Resolve-Path -Path $DriversFolder -ErrorAction Stop).ProviderPath)
$targetPath = [System.IO.Path]::GetFullPath((Resolve-Path -Path $TargetFolder -ErrorAction Stop).ProviderPath)
if ($targetPath -eq $driversRoot) {
WriteLog "Remove-DriverModelFolder skipped deleting Drivers root: $targetPath"
return
}
if (-not ($targetPath.StartsWith($driversRoot, [System.StringComparison]::OrdinalIgnoreCase))) {
WriteLog "Remove-DriverModelFolder skipped path outside Drivers root: $targetPath"
return
}
$contextMessage = if ([string]::IsNullOrWhiteSpace($Description)) { $targetPath } else { "$Description ($targetPath)" }
WriteLog "Removing driver folder $contextMessage due to failure."
Remove-Item -Path $targetPath -Recurse -Force -ErrorAction SilentlyContinue
}
catch {
WriteLog "Remove-DriverModelFolder failed for $($TargetFolder): $($_.Exception.Message)"
}
}
# Helper function to get models for a selected Make and standardize them
function Get-ModelsForMake {
param( param(
[Parameter(Mandatory = $true)] [Parameter(Mandatory = $true)]
[string]$SelectedMake, [string]$SelectedMake,