mirror of
https://github.com/rbalsleyMSFT/FFU.git
synced 2026-06-14 02:09:35 -06:00
Improves driver downloads by using cached links
Reduces unnecessary Download Center requests by preferring cached file details when available Falls back to downloading/parsing the page only on cache miss, then backfills the cache for future runs Adds error handling and logging around cache load/update to avoid download failures from cache issues
This commit is contained in:
@@ -185,83 +185,123 @@ function Save-MicrosoftDriversTask {
|
|||||||
### GET THE DOWNLOAD LINK
|
### GET THE DOWNLOAD LINK
|
||||||
$status = "Getting download link..."
|
$status = "Getting download link..."
|
||||||
if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $modelName -Status $status }
|
if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $modelName -Status $status }
|
||||||
WriteLog "Getting download page content for $modelName from $modelLink"
|
|
||||||
$OriginalVerbosePreference = $VerbosePreference
|
|
||||||
$VerbosePreference = 'SilentlyContinue'
|
|
||||||
# Use passed-in UserAgent and Headers
|
|
||||||
$downloadPageContent = Invoke-WebRequest -Uri $modelLink -UseBasicParsing -Headers $Headers -UserAgent $UserAgent
|
|
||||||
$VerbosePreference = $OriginalVerbosePreference
|
|
||||||
WriteLog "Complete"
|
|
||||||
|
|
||||||
$status = "Parsing download page..."
|
# Initialize Win10/Win11 link variables
|
||||||
if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $modelName -Status $status }
|
$win10Link = $null
|
||||||
WriteLog "Parsing download page for file"
|
$win10FileName = $null
|
||||||
$scriptPattern = '<script>window.__DLCDetails__={(.*?)}<\/script>'
|
$win11Link = $null
|
||||||
$scriptMatch = [regex]::Match($downloadPageContent.Content, $scriptPattern)
|
$win11FileName = $null
|
||||||
|
|
||||||
if ($scriptMatch.Success) {
|
# Prefer cached Download Center details (Source C) to avoid unnecessary internet calls and cache rewrites
|
||||||
$scriptContent = $scriptMatch.Groups[1].Value
|
$useCachedDownloadCenterDetails = $false
|
||||||
# $downloadFilePattern = '"name":"(.*?)",.*?"url":"(.*?)"'
|
try {
|
||||||
$downloadFilePattern = '"name":"([^"]+\.(?:msi|zip))",[^}]*?"url":"(.*?)"'
|
$cache = Import-SurfaceDriverIndexCache -DriversFolder $DriversFolder
|
||||||
$downloadFileMatches = [regex]::Matches($scriptContent, $downloadFilePattern, [System.Text.RegularExpressions.RegexOptions]::IgnoreCase)
|
$cachedDetails = @($cache.DownloadCenterDetails | Where-Object { $_.Link -eq $modelLink } | Select-Object -First 1)
|
||||||
|
if ($cachedDetails.Count -gt 0 -and $cachedDetails[0].Files -and $cachedDetails[0].Files.Count -gt 0) {
|
||||||
|
$useCachedDownloadCenterDetails = $true
|
||||||
|
WriteLog "Surface cache: Using cached Download Center details for $modelName from $modelLink"
|
||||||
|
|
||||||
|
foreach ($downloadFile in @($cachedDetails[0].Files)) {
|
||||||
|
if ($null -eq $downloadFile) { continue }
|
||||||
|
$currentFileName = $downloadFile.Name
|
||||||
|
$fileUrl = $downloadFile.Url
|
||||||
|
if ([string]::IsNullOrWhiteSpace($currentFileName) -or [string]::IsNullOrWhiteSpace($fileUrl)) { continue }
|
||||||
|
|
||||||
$win10Link = $null
|
if ($currentFileName -match "Win10") {
|
||||||
$win10FileName = $null
|
$win10Link = $fileUrl
|
||||||
$win11Link = $null
|
$win10FileName = $currentFileName
|
||||||
$win11FileName = $null
|
WriteLog "Found Win10 link (cached): $win10FileName"
|
||||||
|
}
|
||||||
# Iterate through all matches to find potential Win10 and Win11 links
|
elseif ($currentFileName -match "Win11") {
|
||||||
foreach ($downloadFile in $downloadFileMatches) {
|
$win11Link = $fileUrl
|
||||||
$currentFileName = $downloadFile.Groups[1].Value
|
$win11FileName = $currentFileName
|
||||||
$fileUrl = $downloadFile.Groups[2].Value
|
WriteLog "Found Win11 link (cached): $win11FileName"
|
||||||
|
}
|
||||||
if ($currentFileName -match "Win10") {
|
|
||||||
$win10Link = $fileUrl
|
|
||||||
$win10FileName = $currentFileName
|
|
||||||
WriteLog "Found Win10 link: $win10FileName"
|
|
||||||
}
|
|
||||||
elseif ($currentFileName -match "Win11") {
|
|
||||||
$win11Link = $fileUrl
|
|
||||||
$win11FileName = $currentFileName
|
|
||||||
WriteLog "Found Win11 link: $win11FileName"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
WriteLog "Surface cache: Failed loading cached Download Center details for '$modelName'. Error: $($_.Exception.Message)"
|
||||||
|
}
|
||||||
|
|
||||||
# Update local cache with Download Center file details (Source C) for this model.
|
# Cache miss: download and parse the model's Download Center page (Source C), then backfill the cache
|
||||||
# This runs during download (not during Get Models) so it won't slow the listview population.
|
if (-not $useCachedDownloadCenterDetails) {
|
||||||
try {
|
WriteLog "Getting download page content for $modelName from $modelLink"
|
||||||
$filesForCache = [System.Collections.Generic.List[pscustomobject]]::new()
|
$OriginalVerbosePreference = $VerbosePreference
|
||||||
if ($win10Link -and $win10FileName) {
|
$VerbosePreference = 'SilentlyContinue'
|
||||||
$filesForCache.Add([pscustomobject]@{ Name = $win10FileName; Url = $win10Link })
|
# Use passed-in UserAgent and Headers
|
||||||
}
|
$downloadPageContent = Invoke-WebRequest -Uri $modelLink -UseBasicParsing -Headers $Headers -UserAgent $UserAgent
|
||||||
if ($win11Link -and $win11FileName) {
|
$VerbosePreference = $OriginalVerbosePreference
|
||||||
$filesForCache.Add([pscustomobject]@{ Name = $win11FileName; Url = $win11Link })
|
WriteLog "Complete"
|
||||||
|
|
||||||
|
$status = "Parsing download page..."
|
||||||
|
if ($null -ne $ProgressQueue) { Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $modelName -Status $status }
|
||||||
|
WriteLog "Parsing download page for file"
|
||||||
|
$scriptPattern = '<script>window.__DLCDetails__={(.*?)}<\/script>'
|
||||||
|
$scriptMatch = [regex]::Match($downloadPageContent.Content, $scriptPattern)
|
||||||
|
|
||||||
|
if ($scriptMatch.Success) {
|
||||||
|
$scriptContent = $scriptMatch.Groups[1].Value
|
||||||
|
# $downloadFilePattern = '"name":"(.*?)",.*?"url":"(.*?)"'
|
||||||
|
$downloadFilePattern = '"name":"([^"]+\.(?:msi|zip))",[^}]*?"url":"(.*?)"'
|
||||||
|
$downloadFileMatches = [regex]::Matches($scriptContent, $downloadFilePattern, [System.Text.RegularExpressions.RegexOptions]::IgnoreCase)
|
||||||
|
|
||||||
|
# Iterate through all matches to find potential Win10 and Win11 links
|
||||||
|
foreach ($downloadFile in $downloadFileMatches) {
|
||||||
|
$currentFileName = $downloadFile.Groups[1].Value
|
||||||
|
$fileUrl = $downloadFile.Groups[2].Value
|
||||||
|
|
||||||
|
if ($currentFileName -match "Win10") {
|
||||||
|
$win10Link = $fileUrl
|
||||||
|
$win10FileName = $currentFileName
|
||||||
|
WriteLog "Found Win10 link: $win10FileName"
|
||||||
|
}
|
||||||
|
elseif ($currentFileName -match "Win11") {
|
||||||
|
$win11Link = $fileUrl
|
||||||
|
$win11FileName = $currentFileName
|
||||||
|
WriteLog "Found Win11 link: $win11FileName"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($filesForCache.Count -gt 0) {
|
# Update local cache with Download Center file details (Source C) for this model.
|
||||||
$cache = Import-SurfaceDriverIndexCache -DriversFolder $DriversFolder
|
# This runs during download (not during Get Models) so it won't slow the listview population.
|
||||||
$detailsEntry = [pscustomobject][ordered]@{
|
try {
|
||||||
Model = $modelName
|
$filesForCache = [System.Collections.Generic.List[pscustomobject]]::new()
|
||||||
Link = $modelLink
|
if ($win10Link -and $win10FileName) {
|
||||||
Files = @($filesForCache)
|
$filesForCache.Add([pscustomobject]@{ Name = $win10FileName; Url = $win10Link })
|
||||||
|
}
|
||||||
|
if ($win11Link -and $win11FileName) {
|
||||||
|
$filesForCache.Add([pscustomobject]@{ Name = $win11FileName; Url = $win11Link })
|
||||||
}
|
}
|
||||||
|
|
||||||
$newDetails = [System.Collections.Generic.List[pscustomobject]]::new()
|
if ($filesForCache.Count -gt 0) {
|
||||||
foreach ($item in @($cache.DownloadCenterDetails)) {
|
$cache = Import-SurfaceDriverIndexCache -DriversFolder $DriversFolder
|
||||||
if ($null -ne $item -and $item.PSObject.Properties['Link'] -and $item.Link -ne $modelLink) {
|
$detailsEntry = [pscustomobject][ordered]@{
|
||||||
$newDetails.Add($item)
|
Model = $modelName
|
||||||
|
Link = $modelLink
|
||||||
|
Files = @($filesForCache)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
$newDetails.Add($detailsEntry)
|
|
||||||
$cache.DownloadCenterDetails = @($newDetails)
|
|
||||||
Save-SurfaceDriverIndexCache -Cache $cache -DriversFolder $DriversFolder
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
WriteLog "Surface cache: Failed updating Download Center details cache for '$modelName'. Error: $($_.Exception.Message)"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
$newDetails = [System.Collections.Generic.List[pscustomobject]]::new()
|
||||||
|
foreach ($item in @($cache.DownloadCenterDetails)) {
|
||||||
|
if ($null -ne $item -and $item.PSObject.Properties['Link'] -and $item.Link -ne $modelLink) {
|
||||||
|
$newDetails.Add($item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$newDetails.Add($detailsEntry)
|
||||||
|
$cache.DownloadCenterDetails = @($newDetails)
|
||||||
|
Save-SurfaceDriverIndexCache -Cache $cache -DriversFolder $DriversFolder
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
WriteLog "Surface cache: Failed updating Download Center details cache for '$modelName'. Error: $($_.Exception.Message)"
|
||||||
|
}
|
||||||
|
|
||||||
|
$useCachedDownloadCenterDetails = $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($useCachedDownloadCenterDetails) {
|
||||||
# Decision logic to select the appropriate download link
|
# Decision logic to select the appropriate download link
|
||||||
$downloadLink = $null
|
$downloadLink = $null
|
||||||
$fileName = $null
|
$fileName = $null
|
||||||
|
|||||||
Reference in New Issue
Block a user