Public/Save-LatestUpdate.ps1
Function Save-LatestUpdate { <# .SYNOPSIS Downloads the latest cumulative update passed from Get-LatestUpdate. .DESCRIPTION Downloads the latest cumulative update passed from Get-LatestUpdate to a local folder. Then do one or more of the following: - Import the update into an MDT share with Import-LatestUpdate to speed up deployment of Windows (reference images etc.) - Apply the update to an offline WIM using DISM - Deploy the update with ConfigMgr (if not using WSUS) .NOTES Author: Aaron Parker Twitter: @stealthpuppy .LINK https://docs.stealthpuppy.com/latestupdate .PARAMETER Updates The array of latest cumulative updates retreived by Get-LatestUpdate. .PARAMETER Path A destination path for downloading the cumulative updates to. This path must exist. Uses the current diretory by default. .PARAMETER ForceWebRequest Forces the use of Invoke-WebRequest over Start-BitsTransfer on Windows PowerShell. .EXAMPLE Get-LatestUpdate | Save-LatestUpdate Description: Retreives the latest Windows 10 Cumulative Update with Get-LatestUpdate and passes the array of updates to Save-LatestUpdate on the pipeline. Save-LatestUpdate then downloads the latest updates to the current directory. .EXAMPLE $Updates = Get-LatestUpdate -WindowsVersion Windows10 -Build 14393 Save-LatestUpdate -Updates $Updates -Path C:\Temp\Update Description: Retreives the latest Windows 10 build 14393 (1607) Cumulative Update with Get-LatestUpdate, saved to the variable $Updates. Save-LatestUpdate then downloads the latest updates to C:\Temp\Update. .EXAMPLE $Updates = Get-LatestUpdate Save-LatestUpdate -Updates $Updates -Path C:\Temp\Update -ForceWebRequest Description: Retreives the latest Windows 10 build Cumulative Update with Get-LatestUpdate, saved to the variable $Updates. Save-LatestUpdate then downloads the latest updates to C:\Temp\Update using Invoke-WebRequest instead of Start-BitsTransfer. #> [CmdletBinding(SupportsShouldProcess = $True)] [OutputType([Array])] Param( [Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True, ` HelpMessage = "The array of updates from Get-LatestUpdate.")] [ValidateNotNullOrEmpty()] [Array] $Updates, [Parameter(Mandatory = $False, Position = 1, ValueFromPipeline = $False, ` HelpMessage = "Specify a target path to download the update(s) to.")] [ValidateNotNullOrEmpty()] [ValidateScript( { If (!(Test-Path -Path $_ -PathType 'Container')) { Throw "Cannot find path $_" } Return $True })] [String] $Path = $PWD, [Parameter(Mandatory = $False)] [String] $ProxyURL, [Parameter(Mandatory = $False)] [pscredential] $ProxyCredentials, [Parameter(Mandatory = $False)] [switch] $ForceWebRequest, [Parameter(Mandatory = $False)] [switch] $Force ) Begin { $Path = Get-ValidPath $Path $output = @() } Process { # Step through each update in $Updates ForEach ($update in $Updates) { # Create the target file path where the update will be saved $filename = Split-Path $update.URL -Leaf $target = Join-Path $Path $filename $output += $target Write-Verbose "Download target will be $target" # If the update is not already downloaded, download it. If (!(Test-Path -Path $target) -or $Force.IsPresent) { If ($ForceWebRequest -or (Test-PSCore)) { # Running on PowerShell Core or ForceWebRequest If ($pscmdlet.ShouldProcess($update.URL, "WebDownload")) { try { $WebRequestParams = @{ Uri = $update.URL OutFile = $target UseBasicParsing = $true ErrorAction = "Stop" } if ($ProxyUrl) { $WebRequestParams.Proxy = $ProxyUrl } if ($ProxyCredentials) { $WebRequestParams.ProxyCredentials = $ProxyCredentials } Invoke-WebRequest @WebRequestParams } catch { Throw $_ } } } Else { # Running on Windows PowerShell If ($pscmdlet.ShouldProcess($(Split-Path $update.URL -Leaf), "BitsDownload")) { try { $BitsParams = @{ Source = $update.URL Destination = $target Priority = "High" DisplayName = $update.Note Description = "Downloading $($update.URL)" ErrorAction = "Stop" } if ($ProxyURL) { # Set priority to Foreground because the proxy will remove the Range protocol header $BitsParams.Priority = "Foreground" $BitsParams.ProxyUsage = "Override" $BitsParams.ProxyList = $ProxyURL } if ($ProxyCredentials) { $BitsParams.ProxyCredential = $ProxyCredentials } Start-BitsTransfer @BitsParams } catch { Throw $_ } } } } Else { Write-Verbose "File exists: $target. Skipping download." } } } End { Write-Output $output } } |