private/driverpack/Get-OSDCloudCatalogLenovo.ps1
|
function Get-OSDCloudCatalogLenovo { <# .SYNOPSIS Downloads and parses the Lenovo driver pack catalog for Windows 11. .DESCRIPTION Retrieves the latest Lenovo SCCM driver pack catalog from Lenovo's download site, parses the XML to create a catalog of available Windows 11 driver packs. Falls back to offline catalog if download fails. .EXAMPLE Get-OSDCloudCatalogLenovo Retrieves the Lenovo driver pack catalog for Windows 11. .OUTPUTS PSCustomObject[] Returns custom objects with driver pack information including Name, Model, SystemId, URL, ReleaseDate, and other metadata. .NOTES Catalog is downloaded from https://download.lenovo.com/cdrt/td/catalogv2.xml #> [CmdletBinding()] param () begin { Write-Verbose "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] Start" #================================================= # Catalogs $localDriverPackCatalog = Join-Path (Get-OSDCloudModulePath) $OSDCloudModule.lenovo.driverpackcataloglocal $oemDriverPackCatalog = $OSDCloudModule.lenovo.driverpackcatalogoem $tempCatalogPath = "$($env:TEMP)\osdcloud-driverpack-lenovo.xml" #================================================= # Build realtime catalog from online source, if fails fallback to offline catalog try { if (-not (Test-Path $tempCatalogPath)) { Write-Verbose "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] Downloading Lenovo driver pack catalog from $oemDriverPackCatalog" $sourceContent = Invoke-RestMethod -Uri $oemDriverPackCatalog -UseBasicParsing -ErrorAction Stop if ($sourceContent) { Write-Verbose "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] Processing catalog content" # Remove BOM (Byte Order Mark) from the beginning of the content $catalogContent = $sourceContent.Substring(3) $catalogContent | Out-File -FilePath $tempCatalogPath -Encoding utf8 -Force [xml]$XmlCatalogContent = $catalogContent } } else { Write-Verbose "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] Using temp catalog" if (Test-Path $tempCatalogPath) { Write-Verbose "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] Loading temp catalog from $tempCatalogPath" [xml]$XmlCatalogContent = Get-Content -Path $tempCatalogPath -Raw } } } catch { Write-Verbose "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] Failed to download DriverPack catalog: $($_.Exception.Message)" Write-Verbose "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] Falling back to local catalog" } # Load offline catalog if online catalog failed if (-not $XmlCatalogContent) { Write-Verbose "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] Loading offline catalog from $localDriverPackCatalog" [xml]$XmlCatalogContent = Get-Content -Path $localDriverPackCatalog -Raw } # Validate catalog content if (-not $XmlCatalogContent) { $errorRecord = [System.Management.Automation.ErrorRecord]::new( [System.Exception]::new("Failed to load catalog content"), 'CatalogLoadFailed', [System.Management.Automation.ErrorCategory]::InvalidData, $tempCatalogPath ) $PSCmdlet.ThrowTerminatingError($errorRecord) } } process { #================================================= # Build Catalog #================================================= Write-Verbose "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] Building driver pack catalog" $CatalogVersion = Get-Date -Format yy.MM.dd Write-Verbose "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] Catalog version: $CatalogVersion" $ModelList = $XmlCatalogContent.ModelList.Model #================================================= # Create Object #================================================= $Results = foreach ($Model in $ModelList) { foreach ($Item in $Model.SCCM) { $DownloadUrl = $Item.'#text' # Release date is in this format: 2022-09-28 $ReleaseDate = $Item.date # Need to convert it to this format: 22.09.28 $ReleaseDate = Get-Date $ReleaseDate -Format "yy.MM.dd" $OSVersion = $Item.version if ($OSVersion -eq '*') { $OSVersion = $null } $HashMD5 = $Item.crc if ($Item.os -eq 'win11') { $OperatingSystem = "Windows 11" } else { continue } $NewName = "Lenovo $($Model.name) [$ReleaseDate]" $ObjectProperties = [Ordered]@{ CatalogVersion = $CatalogVersion ReleaseDate = $ReleaseDate Name = $NewName Manufacturer = 'Lenovo' Model = $Model.name SystemId = $Model.Types.Type.split(',').ForEach({$_.Trim()}) FileName = $DownloadUrl | Split-Path -Leaf Url = $DownloadUrl OperatingSystem = $OperatingSystem OSArchitecture = 'amd64' OSVersion = $OSVersion HashMD5 = $HashMD5 } New-Object -TypeName PSObject -Property $ObjectProperties } } #================================================= # Cleanup Catalog #================================================= Write-Verbose "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] Filtering to latest driver packs per model" $Results = $Results | Sort-Object Model, OSVersion -Descending | Group-Object Model | ForEach-Object {$_.Group | Select-Object -First 1} $Results = $Results | Sort-Object Model, OSVersion -Descending | Group-Object HashMD5 | ForEach-Object {$_.Group | Select-Object -First 1} #================================================= # Sort Results #================================================= $Results = $Results | Sort-Object Model, OSVersion -Descending Write-Verbose "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] Found $($Results.Count) Windows 11 driver packs" $Results } end { #================================================= if ($VerbosePreference -eq 'Continue' -or $DebugPreference -eq 'Continue') { $Results | ConvertTo-Json -Depth 10 | Out-File -FilePath "$env:Temp\osdcloud-driverpack-lenovo.json" -Encoding utf8 } if (Test-Path $tempCatalogPath) { Write-Verbose "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] Removing temporary catalog file" Remove-Item -Path $tempCatalogPath -Force -ErrorAction SilentlyContinue } #================================================= Write-Verbose "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] End" #================================================= } } |