Last active
December 28, 2021 00:35
-
-
Save Smalls1652/855e6a0894d31dc1fd09271a924640e0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<#PSScriptInfo | |
.VERSION 2021.12.0 | |
.GUID 9332350c-f337-4184-a850-a5c9367aac55 | |
.AUTHOR Tim Small | |
.COMPANYNAME Smalls.Online | |
.COPYRIGHT 2021 | |
.TAGS | |
.LICENSEURI | |
.PROJECTURI | |
.ICONURI | |
.EXTERNALMODULEDEPENDENCIES | |
.REQUIREDSCRIPTS | |
.EXTERNALSCRIPTDEPENDENCIES | |
.RELEASENOTES | |
.PRIVATEDATA | |
#> | |
<# | |
.SYNOPSIS | |
WSUS Update Catalog Downloader | |
.DESCRIPTION | |
Download the latest copy of the WSUS update catalog. | |
.PARAMETER OutDir | |
The directory to save the 'wsusscn2.cab' file to. | |
.PARAMETER ForceDownload | |
Force the download of the 'wsussc2.cab' file. | |
.EXAMPLE | |
PS C:\> Invoke-DownloadWsusCab.ps1 -OutDir ".\wsus\" | |
Downloads 'wsusscn2.cab' to a specified output directory. | |
.EXAMPLE | |
PS C:\> Invoke-DownloadWsusCab.ps1 | |
Downloads 'wsusscn2.cab' to the current location. | |
.EXAMPLE | |
PS C:\> Invoke-DownloadWsusCab.ps1 -OutDir ".\wsus\" -ForceDownload | |
Downloads 'wsusscn2.cab' even if the current locally downloaded copy is up-to-date. | |
#> | |
#Requires -Version 7.0.0 | |
[CmdletBinding(SupportsShouldProcess, ConfirmImpact = "High")] | |
param( | |
[Parameter(Position = 0)] | |
[ValidateNotNullOrEmpty()] | |
[string]$OutDir = ".", | |
[Parameter(Position = 1)] | |
[switch]$ForceDownload | |
) | |
$resolvedOutPath = (Resolve-Path -Path $OutDir -ErrorAction "Stop").Path | |
$outPathItem = Get-Item -Path $resolvedOutPath | |
if ([System.IO.FileAttributes]::Directory -notin $outPathItem.Attributes) { | |
$PSCmdlet.ThrowTerminatingError( | |
[System.Management.Automation.ErrorRecord]::new( | |
[System.IO.IOException]::new("The supplied output path is not a directory."), | |
"OutputPathNotDirectory", | |
[System.Management.Automation.ErrorCategory]::InvalidArgument, | |
$outPathItem | |
) | |
) | |
} | |
$cabFileOutPath = Join-Path -Path $resolvedOutPath -ChildPath "wsusscn2.cab" | |
$cabFileLastUpdatedFilePath = Join-Path -Path $resolvedOutPath -ChildPath "wsussc2.cab.last-modified" | |
$cabShortLinkUri = "https://go.microsoft.com/fwlink/p/?linkid=74689" | |
# Create the HttpClient object. | |
$httpClient = [System.Net.Http.HttpClient]::new() | |
# Get the current cab file location from the quick link | |
$shortLinkRedirectReqMsg = [System.Net.Http.HttpRequestMessage]::new( | |
[System.Net.Http.HttpMethod]::Head, | |
$cabShortLinkUri | |
) | |
$shortLinkRedirectRsp = $httpClient.SendAsync($shortLinkRedirectReqMsg).GetAwaiter().GetResult() | |
$cabDownloadUri = $shortLinkRedirectRsp.Headers.Location | |
Write-Verbose "Current CAB file is located at: $($cabDownloadUri)" | |
$shortLinkRedirectRsp.Dispose() | |
$shortLinkRedirectReqMsg.Dispose() | |
# Get info about the latest 'wsusscn2.cab' file | |
Write-Verbose "Getting latest CAB file info." | |
$currentCabHeadReqMsg = [System.Net.Http.HttpRequestMessage]::new( | |
[System.Net.Http.HttpMethod]::Head, | |
$cabDownloadUri | |
) | |
$currentCabHeadRsp = $httpClient.SendAsync($currentCabHeadReqMsg).GetAwaiter().GetResult() | |
$currentCabModifiedDateTime = $currentCabHeadRsp.Content.Headers.LastModified | |
$currentCabHeadRsp.Dispose() | |
$currentCabHeadReqMsg.Dispose() | |
#Dispose the HttpClient. It's not needed after this point. | |
$httpClient.Dispose() | |
# Process if the CAB file needs to be updated. | |
$shouldDownload = $false | |
# If the script was set to 'Force', then download. | |
if ($ForceDownload -eq $true) { | |
$shouldDownload = $true | |
} | |
# If the CAB file doesn't already exist locally, then download. | |
if (((Test-Path -Path $cabFileOutPath) -eq $false) -and ($shouldDownload -eq $false)) { | |
$shouldDownload = $true | |
} | |
# If the last updated text file exists and 'shouldDownload' is set to false, then check to see | |
# if the locally downloaded copy is older than the currently available copy. | |
if (((Test-Path -Path $cabFileLastUpdatedFilePath) -eq $true) -and ($shouldDownload -eq $false)) { | |
$cabFileLastUpdatedDateTime = [System.DateTimeOffset]::FromUnixTimeMilliseconds((Get-Content -Path $cabFileLastUpdatedFilePath -Raw)) | |
# If the currently available copy's last modified time is not equal to the locally downloaded last updated time, then download. | |
if (($currentCabModifiedDateTime -eq $cabFileLastUpdatedDateTime) -eq $false) { | |
$shouldDownload = $true | |
} | |
else { | |
Write-Warning "The locally downloaded 'wsusscn2.cab' file is already the latest available copy." | |
Write-Warning "If you want to disregard this check, add the '-ForceDownload' parameter." | |
} | |
} | |
else { | |
$shouldDownload = $true | |
} | |
# If 'shouldDownload' is set to true, then start the download process. | |
if ($shouldDownload -eq $true) { | |
Write-Verbose "Latest CAB file will be downloaded." | |
Write-Verbose "Output path will be here: $($cabFileOutPath)" | |
# Check to see if the CAB file already exists locally and prompt to delete if it does. | |
if ((Test-Path -Path $cabFileOutPath) -eq $true) { | |
if ($PSCmdlet.ShouldProcess($cabFileOutPath, "Delete existing file")) { | |
Remove-Item -Path $cabFileOutPath -Force -Recurse -Confirm:$false | |
} | |
else { | |
$PSCmdlet.ThrowTerminatingError( | |
[System.Management.Automation.ErrorRecord]::new( | |
[System.Exception]::new("User cancelled operation."), | |
"UserCancelledOperation", | |
[System.Management.Automation.ErrorCategory]::OperationStopped, | |
$cabFileOutPath | |
) | |
) | |
} | |
} | |
Write-Warning "Downloading 'wsusscn2.cab'. This may take a bit." | |
$ProgressPreference = "SilentlyContinue" | |
Invoke-WebRequest -TimeoutSec (New-TimeSpan -Minutes 5).Seconds -Method "Get" -Uri $cabDownloadUri -OutFile $cabFileOutPath -Verbose:$false | |
$ProgressPreference = "Continue" | |
# Write the last modified time to the 'wsusscn2.cab.last-modified' file. | |
# It's saved as milliseconds in Unix time. | |
$currentCabModifiedDateTime.ToUnixTimeMilliseconds() | Out-File -FilePath $cabFileLastUpdatedFilePath -Force | |
# Write the downloaded file item to the output. | |
$downloadedOutFile = Get-Item -Path $cabFileOutPath | |
Write-Output -InputObject $downloadedOutFile | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment