private/Step-BuildBootInstallWinPEAppAzCopy.ps1
|
#Requires -PSEdition Core function Step-BuildBootInstallWinPEAppAzCopy { <# .SYNOPSIS Downloads, caches, and injects AzCopy into the mounted WinPE image .DESCRIPTION Creates or reuses the microsoft-azcopy cache and, when the corresponding architecture directory is absent, resolves and downloads both amd64 and arm64 AzCopy archives. Downloads use curl.exe when available and otherwise use Invoke-WebRequest. Download failures produce warnings. The function searches the cache for AzCopy.exe matching global BuildMedia.Architecture, copies each match into Windows\System32 in the mounted image, and appends AzCopy to global BuildMedia.InstalledApps for each copy. .EXAMPLE PS> Step-BuildBootInstallWinPEAppAzCopy Populates the AzCopy cache and injects the selected architecture into WinPE. .INPUTS None. This function does not accept pipeline input. .OUTPUTS None. Native download output is silent and web requests write directly to files. .NOTES Author: David Segura Company: Recast Software Version: 0.1.0 Date: 2026-08-28 Requires global BuildMedia with Architecture, MountPath, and InstalledApps properties; global OSDeployModule.BootImage.winpeapps.azcopy; and script OSDeployCorePath. Requires network access for cache misses and Expand-Archive. Modifies the shared cache, mounted image, and global InstalledApps collection. #> [CmdletBinding()] param () $Architecture = $global:BuildMedia.Architecture $MountPath = $global:BuildMedia.MountPath $WinPEAppsPath = Join-Path $Script:OSDeployCorePath 'cache' 'winpe-apps' $azcopyConfig = $global:OSDeployModule.BootImage.winpeapps.azcopy $CacheAzCopy = Join-Path $WinPEAppsPath 'microsoft-azcopy' if (-not (Test-Path -Path $CacheAzCopy)) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] [INFO] Creating AzCopy cache: $CacheAzCopy" New-Item -Path $CacheAzCopy -ItemType Directory -Force | Out-Null } else { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] [INFO] Using AzCopy cache: $CacheAzCopy" } # Download amd64 version if (-not (Test-Path "$CacheAzCopy\amd64")) { $Uri = $azcopyConfig.amd64 try { $DownloadUri = (Invoke-WebRequest -Uri $Uri -Method Head -ErrorAction SilentlyContinue).BaseResponse.RequestMessage.RequestUri.AbsoluteUri if ($DownloadUri) { $FileName = if ($DownloadUri -match 'filename%3D([^&]+)') { [System.Uri]::UnescapeDataString($Matches[1]) } else { Split-Path $DownloadUri -Leaf } if (-not (Test-Path "$CacheAzCopy\$FileName")) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] [INFO] Downloading AzCopy amd64: $FileName" $downloadPath = Join-Path $CacheAzCopy $FileName if (Get-Command 'curl.exe' -ErrorAction SilentlyContinue) { & curl.exe --silent --location --retry 5 --continue-at - --output $downloadPath $DownloadUri } else { Invoke-WebRequest -UseBasicParsing -Uri $DownloadUri -OutFile $downloadPath } Expand-Archive -Path $downloadPath -DestinationPath "$CacheAzCopy\amd64" -Force } } } catch { Write-Warning "[$(Get-Date -Format s)] Failed to download AzCopy amd64: $_" } } # Download arm64 version if (-not (Test-Path "$CacheAzCopy\arm64")) { $Uri = $azcopyConfig.arm64 try { $DownloadUri = (Invoke-WebRequest -Uri $Uri -Method Head -ErrorAction SilentlyContinue).BaseResponse.RequestMessage.RequestUri.AbsoluteUri if ($DownloadUri) { $FileName = if ($DownloadUri -match 'filename%3D([^&]+)') { [System.Uri]::UnescapeDataString($Matches[1]) } else { Split-Path $DownloadUri -Leaf } if (-not (Test-Path "$CacheAzCopy\$FileName")) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] [INFO] Downloading AzCopy arm64: $FileName" $downloadPath = Join-Path $CacheAzCopy $FileName if (Get-Command 'curl.exe' -ErrorAction SilentlyContinue) { & curl.exe --silent --location --retry 5 --continue-at - --output $downloadPath $DownloadUri } else { Invoke-WebRequest -UseBasicParsing -Uri $DownloadUri -OutFile $downloadPath } Expand-Archive -Path $downloadPath -DestinationPath "$CacheAzCopy\arm64" -Force } } } catch { Write-Warning "[$(Get-Date -Format s)] Failed to download AzCopy arm64: $_" } } # Copy AzCopy to WinPE Get-ChildItem -Path "$CacheAzCopy\$Architecture" -Recurse -Include 'AzCopy.exe' -ErrorAction SilentlyContinue | ForEach-Object { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] [INFO] Injecting AzCopy.exe into WinPE" Copy-Item $_.FullName -Destination "$MountPath\Windows\System32" -Force $global:BuildMedia.InstalledApps += 'AzCopy' } } |