public/Save-LSUpdate.ps1
function Save-LSUpdate { <# .SYNOPSIS Downloads a Lenovo update package to disk .PARAMETER Package The Lenovo package or packages to download .PARAMETER Proxy Specifies a proxy server for the connection to Lenovo. Enter the URI of a network proxy server. .PARAMETER ProxyCredential Specifies a user account that has permission to use the proxy server that is specified by the -Proxy parameter. .PARAMETER ProxyUseDefaultCredentials Indicates that the cmdlet uses the credentials of the current user to access the proxy server that is specified by the -Proxy parameter. .PARAMETER ShowProgress Shows a progress animation during the downloading process, recommended for interactive use as downloads can be quite large and without any progress output the script may appear stuck .PARAMETER Force Redownload and overwrite packages even if they have already been downloaded previously .PARAMETER Path The target directory to which to download the packages to. In this directory, a subfolder will be created for each downloaded package. #> [CmdletBinding()] Param ( [Parameter( Position = 0, ValueFromPipeline = $true, Mandatory = $true )] [pscustomobject]$Package, [Uri]$Proxy, [pscredential]$ProxyCredential, [switch]$ProxyUseDefaultCredentials, [switch]$ShowProgress, [switch]$Force, [System.IO.DirectoryInfo]$Path = "$env:TEMP\LSUPackages" ) begin { if ($PSBoundParameters['Debug'] -and $DebugPreference -eq 'Inquire') { Write-Verbose "Adjusting the DebugPreference to 'Continue'." $DebugPreference = 'Continue' } $transfers = [System.Collections.Generic.List[System.Threading.Tasks.Task]]::new() } process { foreach ($PackageToGet in $Package) { Write-Verbose "Processing package '$($PackageToGet.ID) - $($PackageToGet.Title)'" $DownloadDirectory = Join-Path -Path $Path -ChildPath $PackageToGet.ID if (-not (Test-Path -Path $DownloadDirectory -PathType Container)) { Write-Verbose "Destination directory did not exist, created it: '$DownloadDirectory'" $null = New-Item -Path $DownloadDirectory -Force -ItemType Directory } # Ensure all the packages' files are present locally, download if not foreach ($File in $PackageToGet.Files) { $DownloadSrc = $File.AbsoluteLocation $DownloadDest = Join-Path -Path $DownloadDirectory -ChildPath $File.Name Write-Debug "Testing whether PkgFile ${DownloadDest} is already cached, downloading if not" if ($Force -or -not (Test-Path -Path $DownloadDest -PathType Leaf) -or ( (Get-FileHash -Path $DownloadDest -Algorithm SHA256).Hash -ne $File.Checksum)) { # Checking if this package was already downloaded, if yes skipping redownload $webClient = New-WebClient -Proxy $Proxy -ProxyCredential $ProxyCredential -ProxyUseDefaultCredentials $ProxyUseDefaultCredentials Write-Verbose "Starting download of '$DownloadSrc'" $transfers.Add( $webClient.DownloadFileTaskAsync($DownloadSrc, $DownloadDest) ) } } } } end { if ($ShowProgress -and $transfers) { Show-DownloadProgress -Transfers $transfers } else { while ($transfers.IsCompleted -contains $false) { Start-Sleep -Milliseconds 500 } } if ($transfers.Status -contains "Faulted" -or $transfers.Status -contains "Canceled") { $errorString = "Not all packages could be downloaded, the following errors were encountered:" foreach ($transfer in $transfers.Where{ $_.Status -in "Faulted", "Canceled"}) { $errorString += "`r`n$($transfer.AsyncState.AbsoluteUri) : $($transfer.Exception.InnerExceptions.Message)" } Write-Error $errorString } foreach ($webClient in $transfers) { $webClient.Dispose() } } } |