Enhances Dell driver retrieval by resolving missing CabUrl through CatalogIndexPC. Introduces Resolve-DellCabUrlFromModel function for improved reliability. Updates Save-DriversJson and Import-DriversJson functions to handle additional properties (SystemId, CabUrl, CabRelativePath) for Dell models. Refines Get-DellDrivers function to ensure consistent model handling and logging.

This commit is contained in:
rbalsleyMSFT
2025-10-24 15:19:56 -07:00
parent 7dd002396f
commit 4ce9183bd3
4 changed files with 143 additions and 76 deletions
@@ -182,75 +182,35 @@ function Save-DellDriversTask {
if ($WindowsRelease -le 11) {
$cabUrl = $DriverItemData.CabUrl
if ([string]::IsNullOrWhiteSpace($cabUrl)) {
WriteLog "CabUrl missing for '$modelDisplay' falling back to legacy CatalogPC parsing."
# Fallback legacy client method
$catalogCab = Join-Path $makeDriversPath 'CatalogPC.cab'
$catalogXml = Join-Path $makeDriversPath 'CatalogPC.xml'
$catalogUrl = 'http://downloads.dell.com/catalog/CatalogPC.cab'
$need = $true
if (Test-Path $catalogXml) {
if (((Get-Date) - (Get-Item $catalogXml).CreationTime).TotalDays -lt 7) { $need = $false }
WriteLog "CabUrl missing for '$modelDisplay' resolving via CatalogIndexPC."
$resolved = Resolve-DellCabUrlFromModel -DriversFolder $DriversFolder -ModelDisplay $modelDisplay
if ($null -eq $resolved -or [string]::IsNullOrWhiteSpace($resolved.CabUrl)) {
throw "Unable to resolve CabUrl for $modelDisplay from CatalogIndexPC."
}
if ($need) {
if (Test-Path $catalogCab) { Remove-SafeFolder $catalogCab }
if (Test-Path $catalogXml) { Remove-SafeFolder $catalogXml }
Start-BitsTransferWithRetry -Source $catalogUrl -Destination $catalogCab
Invoke-Process -FilePath Expand.exe -ArgumentList """$catalogCab"" ""$catalogXml""" | Out-Null
Remove-Item $catalogCab -Force -ErrorAction SilentlyContinue
$cabUrl = $resolved.CabUrl
# Optionally persist back into the incoming object if property exists
if ($DriverItemData.PSObject.Properties['CabUrl']) {
$DriverItemData.CabUrl = $cabUrl
}
if (-not (Test-Path $catalogXml)) { throw "Legacy fallback failed; missing $catalogXml" }
[xml]$xmlContent = Get-Content -Path $catalogXml -Raw
$baseLocation = "https://$($xmlContent.manifest.baseLocation)/"
$softwareComponents = $xmlContent.Manifest.SoftwareComponent | Where-Object { $_.ComponentType.value -eq 'DRVR' }
$latestDrivers = @{}
foreach ($component in $softwareComponents) {
$models = $component.SupportedSystems.Brand.Model
foreach ($m in $models) {
if ($m.Display.'#cdata-section' -eq $modelDisplay) {
$validOS = $component.SupportedOperatingSystems.OperatingSystem | Where-Object { $_.osArch -eq $WindowsArch }
if (-not $validOS) { continue }
$driverPath = $component.path
$downloadUrl = $baseLocation + $driverPath
$fileName = [IO.Path]::GetFileName($driverPath)
$name = $component.Name.Display.'#cdata-section' -replace '[\\\/\:\*\?\"\<\>\| ]','_' -replace '[\,]','-'
$category = $component.Category.Display.'#cdata-section' -replace '[\\\/\:\*\?\"\<\>\| ]','_'
$version = [version]$component.vendorVersion
$namePrefix = ($name -split '-')[0]
if (-not $latestDrivers[$category]) { $latestDrivers[$category] = @{} }
if (-not $latestDrivers[$category][$namePrefix] -or $latestDrivers[$category][$namePrefix].Version -lt $version) {
$latestDrivers[$category][$namePrefix] = [pscustomobject]@{
Name = $name
DownloadUrl = $downloadUrl
DriverFileName = $fileName
Version = $version
Category = $category
}
}
}
}
}
foreach ($cat in $latestDrivers.Keys) { foreach ($drv in $latestDrivers[$cat].Values) { $packages += $drv } }
}
else {
# Normal new model-based workflow
$modelCabName = [IO.Path]::GetFileName($cabUrl)
if ([string]::IsNullOrWhiteSpace($modelCabName)) { throw "Derived model cab name empty for $modelDisplay" }
$modelCabPath = Join-Path $makeDriversPath $modelCabName
$modelXmlPath = Join-Path $makeDriversPath ([IO.Path]::GetFileNameWithoutExtension($modelCabName) + '.xml')
if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $modelDisplay -Status 'Downloading catalog...' }
if (Test-Path $modelCabPath) { Remove-SafeFolder $modelCabPath }
if (Test-Path $modelXmlPath) { Remove-SafeFolder $modelXmlPath }
Start-BitsTransferWithRetry -Source $cabUrl -Destination $modelCabPath
Invoke-Process -FilePath Expand.exe -ArgumentList """$modelCabPath"" ""$modelXmlPath""" | Out-Null
Remove-Item $modelCabPath -Force -ErrorAction SilentlyContinue
if (-not (Test-Path $modelXmlPath)) { throw "Model XML not found after extraction: $modelXmlPath" }
if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $modelDisplay -Status 'Selecting latest drivers...' }
$packages = Get-DellLatestDriverPackages -ModelXmlPath $modelXmlPath -WindowsArch $WindowsArch -WindowsRelease $WindowsRelease
}
# Model-based workflow (always used for client pathway now)
$modelCabName = [IO.Path]::GetFileName($cabUrl)
if ([string]::IsNullOrWhiteSpace($modelCabName)) { throw "Derived model cab name empty for $modelDisplay" }
$modelCabPath = Join-Path $makeDriversPath $modelCabName
$modelXmlPath = Join-Path $makeDriversPath ([IO.Path]::GetFileNameWithoutExtension($modelCabName) + '.xml')
if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $modelDisplay -Status 'Downloading catalog...' }
if (Test-Path $modelCabPath) { Remove-SafeFolder $modelCabPath }
if (Test-Path $modelXmlPath) { Remove-SafeFolder $modelXmlPath }
Start-BitsTransferWithRetry -Source $cabUrl -Destination $modelCabPath
Invoke-Process -FilePath Expand.exe -ArgumentList """$modelCabPath"" ""$modelXmlPath""" | Out-Null
Remove-Item $modelCabPath -Force -ErrorAction SilentlyContinue
if (-not (Test-Path $modelXmlPath)) { throw "Model XML not found after extraction: $modelXmlPath" }
if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $modelDisplay -Status 'Selecting latest drivers...' }
$packages = Get-DellLatestDriverPackages -ModelXmlPath $modelXmlPath -WindowsArch $WindowsArch -WindowsRelease $WindowsRelease
}
else {
# Server legacy logic unchanged (kept as before)
@@ -225,6 +225,15 @@ function Save-DriversJson {
$modelObject = @{
Name = $driverItem.Model
}
if ($driverItem.PSObject.Properties['SystemId'] -and -not [string]::IsNullOrWhiteSpace($driverItem.SystemId)) {
$modelObject.SystemId = $driverItem.SystemId
}
if ($driverItem.PSObject.Properties['CabUrl'] -and -not [string]::IsNullOrWhiteSpace($driverItem.CabUrl)) {
$modelObject.CabUrl = $driverItem.CabUrl
}
if ($driverItem.PSObject.Properties['CabRelativePath'] -and -not [string]::IsNullOrWhiteSpace($driverItem.CabRelativePath)) {
$modelObject.CabRelativePath = $driverItem.CabRelativePath
}
}
'HP' {
$modelObject = @{
@@ -337,7 +346,7 @@ function Import-DriversJson {
if ($null -ne $existingModel) {
$existingModel.IsSelected = $true
$existingModel.DownloadStatus = "Imported"
if ($makeName -eq 'Microsoft' -and $importedModelObject.PSObject.Properties['Link']) {
if ($existingModel.Link -ne $importedModelObject.Link) {
$existingModel.Link = $importedModelObject.Link
@@ -352,13 +361,35 @@ function Import-DriversJson {
}
if ($importedModelObject.PSObject.Properties['MachineType'] -and $existingModel.PSObject.Properties['MachineType'] -and $existingModel.MachineType -ne $importedModelObject.MachineType) {
$existingModel.MachineType = $importedModelObject.MachineType
$existingModel.Id = $importedModelObject.MachineType # Update Id as well
$existingModel.Id = $importedModelObject.MachineType
$updateExistingLenovo = $true
}
if ($updateExistingLenovo) {
WriteLog "Import-DriversJson: Updated ProductName/MachineType/Id for existing Lenovo model '$($existingModel.Model)'."
}
}
elseif ($makeName -eq 'Dell') {
# Update Dell extended fields if provided
if ($importedModelObject.PSObject.Properties['SystemId'] -and $existingModel.PSObject.Properties['SystemId'] -and -not [string]::IsNullOrWhiteSpace($importedModelObject.SystemId)) {
if ($existingModel.SystemId -ne $importedModelObject.SystemId) {
$existingModel.SystemId = $importedModelObject.SystemId
WriteLog "Import-DriversJson: Updated SystemId for existing Dell model '$($existingModel.Model)'."
}
}
if ($importedModelObject.PSObject.Properties['CabUrl'] -and $existingModel.PSObject.Properties['CabUrl'] -and -not [string]::IsNullOrWhiteSpace($importedModelObject.CabUrl)) {
if ($existingModel.CabUrl -ne $importedModelObject.CabUrl) {
$existingModel.CabUrl = $importedModelObject.CabUrl
WriteLog "Import-DriversJson: Updated CabUrl for existing Dell model '$($existingModel.Model)'."
}
}
if ($importedModelObject.PSObject.Properties['CabRelativePath'] -and $existingModel.PSObject.Properties['CabRelativePath'] -and -not [string]::IsNullOrWhiteSpace($importedModelObject.CabRelativePath)) {
if ($existingModel.CabRelativePath -ne $importedModelObject.CabRelativePath) {
$existingModel.CabRelativePath = $importedModelObject.CabRelativePath
WriteLog "Import-DriversJson: Updated CabRelativePath for existing Dell model '$($existingModel.Model)'."
}
}
}
$existingModelsUpdated++
WriteLog "Import-DriversJson: Marked existing model '$($existingModel.Make) - $($existingModel.Model)' as imported."
}
@@ -395,7 +426,7 @@ function Import-DriversJson {
$newDriverModel = [PSCustomObject]@{
IsSelected = $true
Make = $makeName
Model = $importedModelNameFromObject # Full display name
Model = $importedModelNameFromObject
Link = $importedLink
Id = $importedId
ProductName = $importedProductName
@@ -406,6 +437,18 @@ function Import-DriversJson {
Arch = ""
DownloadStatus = "Imported"
}
if ($makeName -eq 'Dell') {
# Attach optional Dell extended fields if present
if ($importedModelObject.PSObject.Properties['SystemId'] -and -not [string]::IsNullOrWhiteSpace($importedModelObject.SystemId)) {
$newDriverModel | Add-Member -NotePropertyName SystemId -NotePropertyValue $importedModelObject.SystemId
}
if ($importedModelObject.PSObject.Properties['CabUrl'] -and -not [string]::IsNullOrWhiteSpace($importedModelObject.CabUrl)) {
$newDriverModel | Add-Member -NotePropertyName CabUrl -NotePropertyValue $importedModelObject.CabUrl
}
if ($importedModelObject.PSObject.Properties['CabRelativePath'] -and -not [string]::IsNullOrWhiteSpace($importedModelObject.CabRelativePath)) {
$newDriverModel | Add-Member -NotePropertyName CabRelativePath -NotePropertyValue $importedModelObject.CabRelativePath
}
}
$State.Data.allDriverModels.Add($newDriverModel)
$newModelsAdded++
WriteLog "Import-DriversJson: Added new model '$($newDriverModel.Make) - $($newDriverModel.Model)' from import. ID: $($newDriverModel.Id), Link: $($newDriverModel.Link)"
@@ -753,7 +796,16 @@ function Invoke-DownloadSelectedDrivers {
}
'Dell' {
$modelObject = @{
Name = $driverItem.Model # Model is the display name
Name = $driverItem.Model
}
if ($driverItem.PSObject.Properties['SystemId'] -and -not [string]::IsNullOrWhiteSpace($driverItem.SystemId)) {
$modelObject.SystemId = $driverItem.SystemId
}
if ($driverItem.PSObject.Properties['CabUrl'] -and -not [string]::IsNullOrWhiteSpace($driverItem.CabUrl)) {
$modelObject.CabUrl = $driverItem.CabUrl
}
if ($driverItem.PSObject.Properties['CabRelativePath'] -and -not [string]::IsNullOrWhiteSpace($driverItem.CabRelativePath)) {
$modelObject.CabRelativePath = $driverItem.CabRelativePath
}
}
'HP' {