Get-VcRedist.ps1
# Requires -Version 3 Function Get-VcRedist { <# .SYNOPSIS Downloads the Visual C++ Redistributables from an array returned by Get-VcXml. .DESCRIPTION Downloads the Visual C++ Redistributables from an array returned by Get-VcXml into a folder structure that represents release and processor architecture. If the redistributable exists in the specified path, it will not be re-downloaded. .NOTES Name: Get-VcRedist Author: Aaron Parker Twitter: @stealthpuppy .LINK https://stealthpuppy.com .PARAMETER VcList Sepcifies the array that lists the Visual C++ Redistributables to download .EXAMPLE Get-VcRedist -VcXml $VcRedists -Path C:\Redist Description: Downloads the Visual C++ Redistributables listed in VisualCRedistributables.xml to C:\Redist. .PARAMETER Path Specify a target folder to download the Redistributables to, otherwise use the current folder. .EXAMPLE Get-VcXml | Get-VcRedist -Path C:\Redist Description: Downloads the Visual C++ Redistributables listed in $VcRedists to C:\Redist. .PARAMETER Release Specifies the release (or version) of the redistributables to download or install. .EXAMPLE Get-VcRedist -VcXml $VcRedists -Release "2012","2013",2017" Description: Downloads only the 2012, 2013 & 2017 releases of the Visual C++ Redistributables listed in $VcRedists .PARAMETER Architecture Specifies the processor architecture to download or install. .EXAMPLE Get-VcList | Get-VcRedist -Path C:\Temp\VcRedist Description: Downloads only the 64-bit versions of the Visual C++ Redistributables listed in $VcRedists. .EXAMPLE Get-VcRedist -VcList $VcRedists -Architecture "x64" Description: Downloads only the 64-bit versions of the Visual C++ Redistributables listed in $VcRedists. #> [CmdletBinding(SupportsShouldProcess = $True)] Param ( [Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $False, ` HelpMessage = ".")] [ValidateNotNull()] [array]$VcList, [Parameter(Mandatory = $False, Position = 1, HelpMessage = "Specify a target path to download the Redistributables to.")] [ValidateScript({ If (Test-Path $_ -PathType 'Container') { $True } Else { Throw "Cannot find path $_" } })] [string]$Path, [Parameter(Mandatory = $False, HelpMessage = "Specify the version of the Redistributables to download.")] [ValidateSet('2005', '2008', '2010', '2012', '2013', '2015', '2017')] [string[]]$Release = @("2008", "2010", "2012", "2013", "2015", "2017"), [Parameter(Mandatory = $False, HelpMessage = "Specify the processor architecture/s to download.")] [ValidateSet('x86', 'x64')] [string[]]$Architecture = @("x86", "x64") ) Begin { $Output = @() } Process { # Filter release and architecture if specified If ($PSBoundParameters.ContainsKey('Release')) { Write-Verbose "Filtering releases for platform." $VcList = $VcList | Where-Object { $_.Release -eq $Release } } If ($PSBoundParameters.ContainsKey('Architecture')) { Write-Verbose "Filtering releases for architecture." $VcList = $VcList | Where-Object { $_.Architecture -eq $Architecture } } # Loop through each Redistributable and download to the target path ForEach ($Vc in $VcList) { Write-Verbose "Downloading: [$($Vc.Name)][$($Vc.Release)][$($Vc.Architecture)]" $Output += $Vc # Create the folder to store the downloaded file. Skip if it exists $Target = "$($(Get-Item -Path $Path).FullName)\$($Vc.Release)\$($Vc.Architecture)\$($Vc.ShortName)" If (Test-Path -Path $Target) { Write-Verbose "Folder '$Target' exists. Skipping." } Else { If ($pscmdlet.ShouldProcess($target, "Create")) { New-Item -Path $Target -Type Directory -Force -ErrorAction SilentlyContinue | Out-Null } } # If the target Redistributable is already downloaded, skip it. # If running on Windows PowerShell use Start-BitsTransfer, otherwise use Invoke-WebRequest If (Test-Path -Path "$Target\$(Split-Path -Path $Vc.Download -Leaf)" -PathType Leaf) { Write-Verbose "Redistributable exists. Skipping." } Else { If (Get-Command Start-BitsTransfer -ErrorAction SilentlyContinue) { If ($pscmdlet.ShouldProcess($Vc.Download, "BitsDownload")) { Start-BitsTransfer -Source $Vc.Download -Destination "$Target\$(Split-Path -Path $Vc.Download -Leaf)" ` -Priority High -ErrorAction Continue -ErrorVariable $ErrorBits ` -DisplayName "Visual C++ Redistributable Download" -Description $Vc.Name } } Else { If ($pscmdlet.ShouldProcess($Vc.Download, "WebDownload")) { Invoke-WebRequest -Uri $Vc.Download -OutFile "$Target\$(Split-Path -Path $Vc.Download -Leaf)" } } } } } End { # Return the $VcList array on the pipeline so that we can act on what was downloaded $Output } } |