Public/Save-LatestUpdate.ps1
Function Save-LatestUpdate { <# .SYNOPSIS Downloads the latest Windows 10 Cumulative, Servicing Stack and Adobe Flash Player updates. .DESCRIPTION Downloads the latest Windows 10 Cumulative, Servicing Stack and Adobe Flash Player updates 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) .EXAMPLE PS C:\> Get-LatestServicingStackUpdate | Save-LatestUpdate This commands reads the the Windows 10 update history feed and returns an object that lists the most recent Windows 10 Servicing Stack Updates. The output is then passed to Save-LatestUpdate and each update is downloaded locally. #> [OutputType([System.Management.Automation.PSObject])] [CmdletBinding(SupportsShouldProcess = $True, HelpUri = "https://docs.stealthpuppy.com/docs/latestupdate/usage/download")] Param( [Parameter(Mandatory = $True, Position = 0, ValueFromPipeline)] [ValidateNotNullOrEmpty()] [System.Management.Automation.PSObject] $Updates, [Parameter(Mandatory = $False, Position = 1)] [ValidateNotNullOrEmpty()] [ValidateScript( { If (Test-Path -Path $_ -PathType 'Container') { Return $True } Else { Throw "Cannot find path $_" } })] [System.String] $Path = $PWD, [Parameter(Mandatory = $False)] [System.String] $Proxy, [Parameter(Mandatory = $False)] [System.Management.Automation.PSCredential] $Credential = [System.Management.Automation.PSCredential]::Empty, [Parameter(Mandatory = $False)] [System.Management.Automation.SwitchParameter] $ForceWebRequest, [Parameter(Mandatory = $False)] [ValidateSet('Foreground', 'High', 'Normal', 'Low')] [System.String] $Priority = "Foreground", [Parameter(Mandatory = $False)] [System.Management.Automation.SwitchParameter] $Force ) # Get module strings from the JSON $resourceStrings = Get-ModuleResource # Output object $downloadedUpdates = New-Object -TypeName System.Collections.ArrayList # Step through each update in $Updates ForEach ($update in $Updates) { # Manage updates with multiple URLs ForEach ($url in $update.URL) { # Create the target file path where the update will be saved $updateDownloadTarget = Join-Path -Path $Path -ChildPath (Split-Path -Path $url -Leaf) # If the update is not already downloaded, download it. If ((Test-Path -Path $updateDownloadTarget) -and (-not $Force.IsPresent)) { Write-Verbose -Message "File exists: $updateDownloadTarget. Skipping download." } Else { If ($ForceWebRequest -or (Test-PSCore)) { If ($pscmdlet.ShouldProcess($url, "WebDownload")) { #Running on PowerShell Core or ForceWebRequest try { $iwrParams = @{ Uri = $url OutFile = $updateDownloadTarget UseBasicParsing = $True ErrorAction = $resourceStrings.Preferences.ErrorAction } If ($PSBoundParameters.ContainsKey($Proxy)) { $params.Proxy = $Proxy } If ($PSBoundParameters.ContainsKey($Credential)) { $params.ProxyCredentials = $Credential } Invoke-WebRequest @iwrParams } catch [System.Net.WebException] { Write-Warning -Message ([string]::Format("Error : {0}", $_.Exception.Message)) } catch [System.Exception] { Write-Warning -Message "$($MyInvocation.MyCommand): failed to download: $url." Throw $_.Exception.Message } } } Else { If ($pscmdlet.ShouldProcess($(Split-Path -Path $url -Leaf), "BitsDownload")) { #Running on Windows PowerShell try { $sbtParams = @{ Source = $url Destination = $updateDownloadTarget Priority = $Priority DisplayName = $update.Note Description = "Downloading $url" ErrorAction = $resourceStrings.Preferences.ErrorAction } If ($PSBoundParameters.ContainsKey($Proxy)) { # Set priority to Foreground because the proxy will remove the Range protocol header $params.Priority = "Foreground" $params.ProxyUsage = "Override" $params.ProxyList = $Proxy } If ($PSBoundParameters.ContainsKey($Credential)) { $params.ProxyCredential = $ProxyCredentials } Start-BitsTransfer @sbtParams } catch [System.Net.WebException] { Write-Warning -Message ([string]::Format("Error : {0}", $_.Exception.Message)) } catch [System.Exception] { Write-Warning -Message "$($MyInvocation.MyCommand): failed to download: $url." Throw $_.Exception.Message } } } If (Test-Path -Path $updateDownloadTarget) { $PSObject = [PSCustomObject] @{ KB = $update.KB Note = $update.Note Path = (Resolve-Path -Path $updateDownloadTarget) } $downloadedUpdates.Add($PSObject) | Out-Null } Else { Write-Warning -Message "$($MyInvocation.MyCommand): failed to download [$updateDownloadTarget]." } } } } # Output results to the pipeline Write-Output -InputObject $downloadedUpdates } |