@ -16,15 +16,27 @@
- LTS - most current supported release
- 2 -part version in a format A . B - represents a specific release
examples : 2.0 , 1.0
- Branch name
examples : release / 2.0 . 0 , Master
Note : The version parameter overrides the channel parameter .
- 3 -part version in a format A . B . Cxx - represents a specific SDK release
examples : 5.0 . 1xx , 5.0 . 2xx
Supported since 5.0 release
Note : The version parameter overrides the channel parameter when any version other than 'latest' is used .
. PARAMETER Quality
Download the latest build of specified quality in the channel . The possible values are : daily , signed , validated , preview , GA .
Works only in combination with channel . Not applicable for current and LTS channels and will be ignored if those channels are used .
For SDK use channel in A . B . Cxx format : using quality together with channel in A . B format is not supported .
Supported since 5.0 release .
Note : The version parameter overrides the channel parameter when any version other than 'latest' is used , and therefore overrides the quality .
. PARAMETER Version
Default : latest
Represents a build version on specific channel . Possible values :
- latest - most latest build on specific channel
- 3 -part version in a format A . B . C - represents specific version of build
examples : 2.0 . 0 -preview2 - 006120 , 1.1 . 0
. PARAMETER Internal
Download internal builds . Requires providing credentials via -FeedCredential parameter .
. PARAMETER FeedCredential
Token to access Azure feed . Used as a query string to append to the Azure feed .
This parameter typically is not specified .
. PARAMETER InstallDir
Default : % LocalAppData % \ Microsoft \ dotnet
Path to where to install dotnet . Note that binaries will be placed directly in a given directory .
@ -59,9 +71,6 @@
. PARAMETER UncachedFeed
This parameter typically is not changed by the user .
It allows changing the URL for the Uncached feed used by this installer .
. PARAMETER FeedCredential
Used as a query string to append to the Azure feed .
It allows changing the URL to use non-public blob storage accounts .
. PARAMETER ProxyAddress
If set , the installer will use the proxy when making web requests
. PARAMETER ProxyUseDefaultCredentials
@ -81,11 +90,12 @@
[ cmdletbinding ( ) ]
param (
[ string ] $Channel = " LTS " ,
[ string ] $Quality ,
[ string ] $Version = " Latest " ,
[ switch ] $Internal ,
[ string ] $JSonFile ,
[ string ] $InstallDir = " <auto> " ,
[ string ] $Architecture = " <auto> " ,
[ ValidateSet ( " dotnet " , " aspnetcore " , " windowsdesktop " , IgnoreCase = $false ) ]
[ string ] $Runtime ,
[ Obsolete ( " This parameter may be removed in a future version of this script. The recommended alternative is '-Runtime dotnet'. " ) ]
[ switch ] $SharedRuntime ,
@ -205,7 +215,7 @@ function Get-Machine-Architecture() {
function Get-CLIArchitecture-From-Architecture([string]$Architecture ) {
Say-Invocation $MyInvocation
switch ( $Architecture . ToLower ( ) ) {
switch ( $Architecture . ToLower Invariant ( ) ) {
{ $_ -eq " <auto> " } { return Get-CLIArchitecture -From -Architecture $ ( Get-Machine -Architecture ) }
{ ( $_ -eq " amd64 " ) -or ( $_ -eq " x64 " ) } { return " x64 " }
{ $_ -eq " x86 " } { return " x86 " }
@ -215,6 +225,53 @@ function Get-CLIArchitecture-From-Architecture([string]$Architecture) {
}
}
function Get-NormalizedQuality([string]$Quality ) {
Say-Invocation $MyInvocation
if ( [ string ] :: IsNullOrEmpty ( $Quality ) ) {
return " "
}
switch ( $Quality ) {
{ @ ( " daily " , " signed " , " validated " , " preview " ) -contains $_ } { return $Quality . ToLowerInvariant ( ) }
#ga quality is available without specifying quality, so normalizing it to empty
{ $_ -eq " ga " } { return " " }
default { throw " ' $Quality ' is not a supported value for -Quality option. Supported values are: daily, signed, validated, preview, ga. If you think this is a bug, report it at https://github.com/dotnet/install-scripts/issues. " }
}
}
function Get-NormalizedChannel([string]$Channel ) {
Say-Invocation $MyInvocation
if ( [ string ] :: IsNullOrEmpty ( $Channel ) ) {
return " "
}
if ( $Channel . StartsWith ( 'release/' ) ) {
Say-Warning 'Using branch name with -Channel option is no longer supported with newer releases. Use -Quality option with a channel in X.Y format instead, such as "-Channel 5.0 -Quality Daily."'
}
switch ( $Channel ) {
{ $_ -eq " lts " } { return " LTS " }
{ $_ -eq " current " } { return " current " }
default { return $Channel . ToLowerInvariant ( ) }
}
}
function Get-NormalizedProduct([string]$Runtime ) {
Say-Invocation $MyInvocation
switch ( $Runtime ) {
{ $_ -eq " dotnet " } { return " dotnet-runtime " }
{ $_ -eq " aspnetcore " } { return " aspnetcore-runtime " }
{ $_ -eq " windowsdesktop " } { return " windowsdesktop-runtime " }
{ [ string ] :: IsNullOrEmpty ( $_ ) } { return " dotnet-sdk " }
default { throw " ' $Runtime ' is not a supported value for -Runtime option, supported values are: dotnet, aspnetcore, windowsdesktop. If you think this is a bug, report it at https://github.com/dotnet/install-scripts/issues. " }
}
}
# The version text returned from the feeds is a 1-line or 2-line string:
# For the SDK and the dotnet runtime (2 lines):
# Line 1: # commit_hash
@ -243,7 +300,7 @@ function Load-Assembly([string] $Assembly) {
}
}
function GetHTTPResponse([Uri ] $Uri )
function GetHTTPResponse([Uri ] $Uri , [ bool ] $HeaderOnly , [ bool ] $DisableRedirect , [ bool ] $DisableFeedCredential )
{
Invoke-With -Retry (
{
@ -270,26 +327,42 @@ function GetHTTPResponse([Uri] $Uri)
}
}
$HttpClientHandler = New-Object System . Net . Http . HttpClientHandler
if ( $ProxyAddress ) {
$HttpClientHandler = New-Object System . Net . Http . HttpClientHandler
$HttpClientHandler . Proxy = New-Object System . Net . WebProxy -Property @ {
Address = $ProxyAddress ;
UseDefaultCredentials = $ProxyUseDefaultCredentials ;
BypassList = $ProxyBypassList ;
}
$HttpClient = New-Object System . Net . Http . HttpClient -ArgumentList $HttpClientHandler
}
if ( $DisableRedirect )
{
$HttpClientHandler . AllowAutoRedirect = $false
}
else {
$HttpClient = New-Object System . Net . Http . HttpClient -ArgumentList $HttpClientHandler
$HttpClient = New-Object System . Net . Http . HttpClient
}
# Default timeout for HttpClient is 100s. For a 50 MB download this assumes 500 KB/s average, any less will time out
# 20 minutes allows it to work over much slower connections.
$HttpClient . Timeout = New-TimeSpan -Minutes 20
$Task = $HttpClient . GetAsync ( " ${Uri} ${FeedCredential} " ) . ConfigureAwait ( " false " ) ;
if ( $HeaderOnly ) {
$completionOption = [ System.Net.Http.HttpCompletionOption ] :: ResponseHeadersRead
}
else {
$completionOption = [ System.Net.Http.HttpCompletionOption ] :: ResponseContentRead
}
if ( $DisableFeedCredential ) {
$UriWithCredential = $Uri
}
else {
$UriWithCredential = " ${Uri} ${FeedCredential} "
}
$Task = $HttpClient . GetAsync ( " $UriWithCredential " , $completionOption ) . ConfigureAwait ( " false " ) ;
$Response = $Task . GetAwaiter ( ) . GetResult ( ) ;
if ( ( $null -eq $Response ) -or ( -not ( $Response . IsSuccessStatusCode ) ) ) {
if ( ( $null -eq $Response ) -or ( ( -not $HeaderOnly ) -and ( -not ( $Response . IsSuccessStatusCode ) ) ) ) {
# The feed credential is potentially sensitive info. Do not log FeedCredential to console output.
$DownloadException = [ System.Exception ] " Unable to download $Uri . "
@ -349,6 +422,9 @@ function Get-Latest-Version-Info([string]$AzureFeed, [string]$Channel) {
else {
throw " Invalid value for `$ Runtime "
}
Say-Verbose " Constructed latest.version URL: $VersionFileUrl "
try {
$Response = GetHTTPResponse -Uri $VersionFileUrl
}
@ -411,7 +487,7 @@ function Get-Specific-Version-From-Version([string]$AzureFeed, [string]$Channel,
Say-Invocation $MyInvocation
if ( -not $JSonFile ) {
if ( $Version . ToLower ( ) -eq " latest " ) {
if ( $Version . ToLower Invariant ( ) -eq " latest " ) {
$LatestVersionInfo = Get-Latest -Version -Info -AzureFeed $AzureFeed -Channel $Channel
return $LatestVersionInfo . Version
}
@ -478,58 +554,116 @@ function Get-LegacyDownload-Link([string]$AzureFeed, [string]$SpecificVersion, [
return $PayloadURL
}
function Get-Product-Version([string]$AzureFeed , [ string ] $SpecificVersion ) {
function Get-Product-Version([string]$AzureFeed , [ string ] $SpecificVersion , [ string ] $PackageDownloadLink ) {
Say-Invocation $MyInvocation
if ( $Runtime -eq " dotnet " ) {
$ProductVersionTxtURL = " $AzureFeed /Runtime/ $SpecificVersion /productVersion.txt "
}
elseif ( $Runtime -eq " aspnetcore " ) {
$ProductVersionTxtURL = " $AzureFeed /aspnetcore/Runtime/ $SpecificVersion /productVersion.txt "
}
elseif ( $Runtime -eq " windowsdesktop " ) {
# The windows desktop runtime is part of the core runtime layout prior to 5.0
$ProductVersionTxtURL = " $AzureFeed /Runtime/ $SpecificVersion /productVersion.txt "
if ( $SpecificVersion -match '^(\d+)\.(.*)' )
{
$majorVersion = [ int ] $Matches [ 1 ]
if ( $majorVersion -ge 5 )
{
$ProductVersionTxtURL = " $AzureFeed /WindowsDesktop/ $SpecificVersion /productVersion.txt "
# Try to get the version number, using the productVersion.txt file located next to the installer file.
$ProductVersionTxtURLs = ( Get-Product -Version -Url $AzureFeed $SpecificVersion $PackageDownloadLink -Flattened $true ) ,
( Get-Product -Version -Url $AzureFeed $SpecificVersion $PackageDownloadLink -Flattened $false )
Foreach ( $ProductVersionTxtURL in $ProductVersionTxtURLs ) {
Say-Verbose " Checking for the existence of $ProductVersionTxtURL "
try {
$productVersionResponse = GetHTTPResponse ( $productVersionTxtUrl )
if ( $productVersionResponse . StatusCode -eq 200 ) {
$productVersion = $productVersionResponse . Content . ReadAsStringAsync ( ) . Result . Trim ( )
if ( $productVersion -ne $SpecificVersion )
{
Say " Using alternate version $productVersion found in $ProductVersionTxtURL "
}
return $productVersion
}
else {
Say-Verbose " Got StatusCode $( $productVersionResponse . StatusCode ) when trying to get productVersion.txt at $productVersionTxtUrl . "
}
}
catch {
Say-Verbose " Could not read productVersion.txt at $productVersionTxtUrl (Exception: ' $( $_ . Exception . Message ) '. ) "
}
}
elseif ( -not $Runtime ) {
$ProductVersionTxtURL = " $AzureFeed /Sdk/ $SpecificVersion /productVersion.txt "
}
else {
throw " Invalid value ' $Runtime ' specified for `$ Runtime "
# Getting the version number with productVersion.txt has failed. Try parsing the download link for a version number.
if ( [ string ] :: IsNullOrEmpty ( $PackageDownloadLink ) )
{
Say-Verbose " Using the default value ' $SpecificVersion ' as the product version. "
return $SpecificVersion
}
Say-Verbose " Checking for existence of $ProductVersionTxtURL "
$productVersion = Get-ProductVersionFromDownloadLink $PackageDownloadLink $SpecificVersion
return $productVersion
}
try {
$productVersionResponse = GetHTTPResponse ( $productVersionTxtUrl )
function Get-Product-Version-Url([string]$AzureFeed , [ string ] $SpecificVersion , [ string ] $PackageDownloadLink , [ bool ] $Flattened ) {
Say-Invocation $MyInvocation
if ( $productVersionResponse . StatusCode -eq 200 ) {
$productVersion = $productVersionResponse . Content . ReadAsStringAsync ( ) . Result . Trim ( )
if ( $productVersion -ne $SpecificVersion )
{
Say " Using alternate version $productVersion found in $ProductVersionTxtURL "
}
$majorVersion = $null
if ( $SpecificVersion -match '^(\d+)\.(.*)' ) {
$majorVersion = $Matches [ 1 ] -as [ int ]
}
return $productVersion
$pvFileName = 'productVersion.txt'
if ( $Flattened ) {
if ( -not $Runtime ) {
$pvFileName = 'sdk-productVersion.txt'
}
elseif ( $Runtime -eq " dotnet " ) {
$pvFileName = 'runtime-productVersion.txt'
}
else {
Say-Verbose " Got StatusCode $( $productVersionResponse . StatusCode ) trying to get productVersion.txt at $productVersionTxtUrl , so using default value of $SpecificVersion "
$productVersion = $SpecificVersion
$pvFileName = " $Runtime -productVersion.txt "
}
} catch {
Say-Verbose " Could not read productVersion.txt at $productVersionTxtUrl , so using default value of $SpecificVersion (Exception: ' $( $_ . Exception . Message ) ' ) "
$productVersion = $SpecificVersion
}
return $productVersion
if ( [ string ] :: IsNullOrEmpty ( $PackageDownloadLink ) ) {
if ( $Runtime -eq " dotnet " ) {
$ProductVersionTxtURL = " $AzureFeed /Runtime/ $SpecificVersion / $pvFileName "
}
elseif ( $Runtime -eq " aspnetcore " ) {
$ProductVersionTxtURL = " $AzureFeed /aspnetcore/Runtime/ $SpecificVersion / $pvFileName "
}
elseif ( $Runtime -eq " windowsdesktop " ) {
# The windows desktop runtime is part of the core runtime layout prior to 5.0
$ProductVersionTxtURL = " $AzureFeed /Runtime/ $SpecificVersion / $pvFileName "
if ( $majorVersion -ne $null -and $majorVersion -ge 5 ) {
$ProductVersionTxtURL = " $AzureFeed /WindowsDesktop/ $SpecificVersion / $pvFileName "
}
}
elseif ( -not $Runtime ) {
$ProductVersionTxtURL = " $AzureFeed /Sdk/ $SpecificVersion / $pvFileName "
}
else {
throw " Invalid value ' $Runtime ' specified for `$ Runtime "
}
}
else {
$ProductVersionTxtURL = $PackageDownloadLink . Substring ( 0 , $PackageDownloadLink . LastIndexOf ( " / " ) ) + " / $pvFileName "
}
Say-Verbose " Constructed productVersion link: $ProductVersionTxtURL "
return $ProductVersionTxtURL
}
function Get-ProductVersionFromDownloadLink([string]$PackageDownloadLink , [ string ] $SpecificVersion )
{
Say-Invocation $MyInvocation
#product specific version follows the product name
#for filename 'dotnet-sdk-3.1.404-win-x64.zip': the product version is 3.1.400
$filename = $PackageDownloadLink . Substring ( $PackageDownloadLink . LastIndexOf ( " / " ) + 1 )
$filenameParts = $filename . Split ( '-' )
if ( $filenameParts . Length -gt 2 )
{
$productVersion = $filenameParts [ 2 ]
Say-Verbose " Extracted product version ' $productVersion ' from download link ' $PackageDownloadLink '. "
}
else {
Say-Verbose " Using the default value ' $SpecificVersion ' as the product version. "
$productVersion = $SpecificVersion
}
return $productVersion
}
function Get-User-Share-Path ( ) {
@ -702,15 +836,150 @@ function Prepend-Sdk-InstallRoot-To-Path([string]$InstallRoot, [string]$BinFolde
}
}
function Get-AkaMSDownloadLink([string]$Channel , [ string ] $Quality , [ bool ] $Internal , [ string ] $Product , [ string ] $Architecture ) {
Say-Invocation $MyInvocation
#quality is not supported for LTS or current channel
if ( ! [ string ] :: IsNullOrEmpty ( $Quality ) -and ( @ ( " LTS " , " current " ) -contains $Channel ) ) {
$Quality = " "
Say-Warning " Specifying quality for current or LTS channel is not supported, the quality will be ignored. "
}
Say-Verbose " Retrieving primary payload URL from aka.ms link for channel: ' $Channel ', quality: ' $Quality ' product: ' $Product ', os: 'win', architecture: ' $Architecture '. "
#construct aka.ms link
$akaMsLink = " https://aka.ms/dotnet "
if ( $Internal ) {
$akaMsLink + = " /internal "
}
$akaMsLink + = " / $Channel "
if ( -not [ string ] :: IsNullOrEmpty ( $Quality ) ) {
$akaMsLink + = " / $Quality "
}
$akaMsLink + = " / $Product -win- $Architecture .zip "
Say-Verbose " Constructed aka.ms link: ' $akaMsLink '. "
$akaMsDownloadLink = $null
for ( $maxRedirections = 9 ; $maxRedirections -ge 0 ; $maxRedirections - - )
{
#get HTTP response
#do not pass credentials as a part of the $akaMsLink and do not apply credentials in the GetHTTPResponse function
#otherwise the redirect link would have credentials as well
#it would result in applying credentials twice to the resulting link and thus breaking it, and in echoing credentials to the output as a part of redirect link
$Response = GetHTTPResponse -Uri $akaMsLink -HeaderOnly $true -DisableRedirect $true -DisableFeedCredential $true
Say-Verbose " Received response: `n $Response "
if ( [ string ] :: IsNullOrEmpty ( $Response ) ) {
Say-Verbose " The link ' $akaMsLink ' is not valid: failed to get redirect location. The resource is not available. "
return $null
}
#if HTTP code is 301 (Moved Permanently), the redirect link exists
if ( $Response . StatusCode -eq 301 )
{
try {
$akaMsDownloadLink = $Response . Headers . GetValues ( " Location " ) [ 0 ]
if ( [ string ] :: IsNullOrEmpty ( $akaMsDownloadLink ) ) {
Say-Verbose " The link ' $akaMsLink ' is not valid: server returned 301 (Moved Permanently), but the headers do not contain the redirect location. "
return $null
}
Say-Verbose " The redirect location retrieved: ' $akaMsDownloadLink '. "
# This may yet be a link to another redirection. Attempt to retrieve the page again.
$akaMsLink = $akaMsDownloadLink
continue
}
catch {
Say-Verbose " The link ' $akaMsLink ' is not valid: failed to get redirect location. "
return $null
}
}
elseif ( ( ( $Response . StatusCode -lt 300 ) -or ( $Response . StatusCode -ge 400 ) ) -and ( -not [ string ] :: IsNullOrEmpty ( $akaMsDownloadLink ) ) )
{
# Redirections have ended.
return $akaMsDownloadLink
}
Say-Verbose " The link ' $akaMsLink ' is not valid: failed to retrieve the redirection location. "
return $null
}
Say-Verbose " Aka.ms links have redirected more than the maximum allowed redirections. This may be caused by a cyclic redirection of aka.ms links. "
return $null
}
Say " Note that the intended use of this script is for Continuous Integration (CI) scenarios, where: "
Say " - The SDK needs to be installed without user interaction and without admin rights. "
Say " - The SDK installation doesn't need to persist across multiple CI runs. "
Say " To set up a development environment or to run apps, use installers rather than this script. Visit https://dotnet.microsoft.com/download to get the installer. `r `n "
if ( $Internal -and [ string ] :: IsNullOrWhitespace ( $FeedCredential ) ) {
$message = " Provide credentials via -FeedCredential parameter. "
if ( $DryRun ) {
Say-Warning " $message "
} else {
throw " $message "
}
}
#FeedCredential should start with "?", for it to be added to the end of the link.
#adding "?" at the beginning of the FeedCredential if needed.
if ( ( ! [ string ] :: IsNullOrWhitespace ( $FeedCredential ) ) -and ( $FeedCredential [ 0 ] -ne '?' ) ) {
$FeedCredential = " ? " + $FeedCredential
}
$CLIArchitecture = Get-CLIArchitecture -From -Architecture $Architecture
$SpecificVersion = Get-Specific -Version -From -Version -AzureFeed $AzureFeed -Channel $Channel -Version $Version -JSonFile $JSonFile
$DownloadLink , $EffectiveVersion = Get-Download -Link -AzureFeed $AzureFeed -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture
$LegacyDownloadLink = Get-LegacyDownload -Link -AzureFeed $AzureFeed -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture
$NormalizedQuality = Get-NormalizedQuality $Quality
Say-Verbose " Normalized quality: ' $NormalizedQuality ' "
$NormalizedChannel = Get-NormalizedChannel $Channel
Say-Verbose " Normalized channel: ' $NormalizedChannel ' "
$NormalizedProduct = Get-NormalizedProduct $Runtime
Say-Verbose " Normalized product: ' $NormalizedProduct ' "
$DownloadLink = $null
#try to get download location from aka.ms link
#not applicable when exact version is specified via command or json file
if ( [ string ] :: IsNullOrEmpty ( $JSonFile ) -and ( $Version -eq " latest " ) ) {
$AkaMsDownloadLink = Get-AkaMSDownloadLink -Channel $NormalizedChannel -Quality $NormalizedQuality -Internal $Internal -Product $NormalizedProduct -Architecture $CLIArchitecture
if ( [ string ] :: IsNullOrEmpty ( $AkaMsDownloadLink ) ) {
if ( -not [ string ] :: IsNullOrEmpty ( $NormalizedQuality ) ) {
# if quality is specified - exit with error - there is no fallback approach
Say-Error " Failed to locate the latest version in the channel ' $NormalizedChannel ' with ' $NormalizedQuality ' quality for ' $NormalizedProduct ', os: 'win', architecture: ' $CLIArchitecture '. "
Say-Error " Refer to: https://aka.ms/dotnet-os-lifecycle for information on .NET Core support. "
throw " aka.ms link resolution failure "
}
Say-Verbose " Falling back to latest.version file approach. "
}
else {
Say-Verbose " Retrieved primary named payload URL from aka.ms link: ' $AkaMsDownloadLink '. "
$DownloadLink = $AkaMsDownloadLink
Say-Verbose " Downloading using legacy url will not be attempted. "
$LegacyDownloadLink = $null
#get version from the path
$pathParts = $DownloadLink . Split ( '/' )
if ( $pathParts . Length -ge 2 ) {
$SpecificVersion = $pathParts [ $pathParts . Length - 2 ]
Say-Verbose " Version: ' $SpecificVersion '. "
}
else {
Say-Error " Failed to extract the version from download link ' $DownloadLink '. "
}
#retrieve effective (product) version
$EffectiveVersion = Get-Product -Version -AzureFeed $AzureFeed -SpecificVersion $SpecificVersion -PackageDownloadLink $DownloadLink
Say-Verbose " Product version: ' $EffectiveVersion '. "
}
}
if ( [ string ] :: IsNullOrEmpty ( $DownloadLink ) ) {
$SpecificVersion = Get-Specific -Version -From -Version -AzureFeed $AzureFeed -Channel $Channel -Version $Version -JSonFile $JSonFile
$DownloadLink , $EffectiveVersion = Get-Download -Link -AzureFeed $AzureFeed -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture
$LegacyDownloadLink = Get-LegacyDownload -Link -AzureFeed $AzureFeed -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture
}
$InstallRoot = Resolve-Installation -Path $InstallDir
Say-Verbose " InstallRoot: $InstallRoot "
@ -718,9 +987,9 @@ $ScriptName = $MyInvocation.MyCommand.Name
if ( $DryRun ) {
Say " Payload URLs: "
Say " Primary named payload URL: $ DownloadLink"
Say " Primary named payload URL: $ { DownloadLink} "
if ( $LegacyDownloadLink ) {
Say " Legacy named payload URL: $ LegacyDownloadLink"
Say " Legacy named payload URL: $ { LegacyDownloadLink} "
}
$RepeatableCommand = " .\ $ScriptName -Version `" $SpecificVersion `" -InstallDir `" $InstallRoot `" -Architecture `" $CLIArchitecture `" "
if ( $Runtime -eq " dotnet " ) {
@ -729,11 +998,20 @@ if ($DryRun) {
elseif ( $Runtime -eq " aspnetcore " ) {
$RepeatableCommand + = " -Runtime `" aspnetcore `" "
}
if ( -not [ string ] :: IsNullOrEmpty ( $NormalizedQuality ) )
{
$RepeatableCommand + = " -Quality `" $NormalizedQuality `" "
}
foreach ( $key in $MyInvocation . BoundParameters . Keys ) {
if ( -not ( @ ( " Architecture " , " Channel " , " DryRun " , " InstallDir " , " Runtime " , " SharedRuntime " , " Version " ) -contains $key ) ) {
if ( -not ( @ ( " Architecture " , " Channel " , " DryRun " , " InstallDir " , " Runtime " , " SharedRuntime " , " Version " ," Quality " , " FeedCredential " ) -contains $key ) ) {
$RepeatableCommand + = " - $key `" $( $MyInvocation . BoundParameters [ $key ] ) `" "
}
}
if ( $MyInvocation . BoundParameters . Keys -contains " FeedCredential " ) {
$RepeatableCommand + = " -FeedCredential `" <feedCredential> `" "
}
Say " Repeatable invocation: $RepeatableCommand "
if ( $SpecificVersion -ne $EffectiveVersion )
{
@ -779,9 +1057,16 @@ if ($isAssetInstalled) {
New-Item -ItemType Directory -Force -Path $InstallRoot | Out-Null
$installDrive = $ ( ( Get-Item $InstallRoot ) . PSDrive . Name ) ;
$diskInfo = Get-PSDrive -Name $installDrive
if ( $diskInfo . Free / 1 MB -le 100 ) {
$installDrive = $ ( ( Get-Item $InstallRoot -Force ) . PSDrive . Name ) ;
$diskInfo = $null
try {
$diskInfo = Get-PSDrive -Name $installDrive
}
catch {
Say-Warning " Failed to check the disk space. Installation will continue, but it may fail if you do not have enough disk space. "
}
if ( ( $diskInfo -ne $null ) -and ( $diskInfo . Free / 1 MB -le 100 ) ) {
throw " There is not enough disk space on drive ${installDrive} : "
}
@ -902,42 +1187,42 @@ Say "Note that the script does not resolve dependencies during installation."
Say " To check the list of dependencies, go to https://docs.microsoft.com/dotnet/core/install/windows#dependencies "
Say " Installation finished "
# SIG # Begin signature block
# MIIj jwYJKoZIhvcNAQcCoIIjgDCCI3w CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# MIIj kgYJKoZIhvcNAQcCoIIjgzCCI38 CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABC CNsnhcJvx/hXmM
# w8KjuvvIMDBFonhg9XJFc1QwfTyH4aCCDYEwggX/MIID56ADAgECAhMzAAABh3IX
# chVZQMcJAAAAAAGH MA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABC AGF/0aIv/nK8pL
# ube4cwR/nwps7FSM0D5vjXxuQe3LXaCCDYEwggX/MIID56ADAgECAhMzAAAB32vw
# LpKnSrTQAAAAAAHf MA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
# bmcgUENBIDIwMTEwHhcNMjA wMzA0MTgzOTQ3WhcNMjEwMzAzMTgzOTQ3 WjB0MQsw
# bmcgUENBIDIwMTEwHhcNMjA xMjE1MjEzMTQ1WhcNMjExMjAyMjEzMTQ1 WjB0MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
# AQ DOt8kLc7P3T7MKIhouYHewMFmnq8Ayu7FOhZCQabVwBp2VS4WyB2Qe4TQBT8aB
# znANDEPjHKNdPT8Xz5cNali6XHefS8i/WXtF0vSsP8NEv6mBHuA2p1fw2wB/F0dH
# sJ3GfZ5c0sPJjklsiYqPw59xJ54kM91IOgiO2OUzjNAljPibjCWfH7UzQ1TPHc4d
# weils8GEIrbBRb7IWwiObL12jWT4Yh71NQgvJ9Fn6+UhD9x2uk3dLj84vwt1NuFQ
# itKJxIV0fVsRNR3abQVOLqpDugbr0SzNL6o8xzOHL5OXiGGwg6ekiXA1/2XXY7yV
# Fc39tledDtZjSjNbex1zzwSX AgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQU hov4ZyO96axkJdMjpzu2zVXOJcs w
# AQ C2uxlZEACjqfHkuFyoCwfL25ofI9DZWKt4wEj3JBQ48GPt1UsDv834CcoUUPMn
# s/6CtPoaQ4Thy/kbOOg/zJAnrJeiMQqRe2Lsdb/NSI2gXXX9lad1/yPUDOXo4GNw
# PjXq1JZi+HZV91bUr6ZjzePj1g+bepsqd/HC1XScj0fT3aAxLRykJSzExEBmU9eS
# yuOwUuq+CriudQtWGMdJU650v/KmzfM46Y6lo/MCnnpvz3zEL7PMdUdwqj/nYhGG
# 3UVILxX7tAdMbz7LN+6WOIpT1A41rwaoOVnv+8Ua94HwhjZmu1S73yeV7RZZNxoh
# EegJi9YYssXa7UZUUkCCA+Kn AgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQU OPbML8IdkNGtCfMmVPtvI6VZ8+M w
# UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1
# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrND U4Mzg1 MB8GA1UdIwQYMBaAFEhu
# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrND YzMDA5 MB8GA1UdIwQYMBaAFEhu
# ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu
# bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w
# Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3
# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx
# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEA ixmy
# S6E6vprWD9KFNIB9G5zyMuIjZAOuUJ1EK/Vlg6Fb3ZHXjjUwATKIcXbFuFC6Wr4K
# NrU4DY/sBVqmab5AC/je3bpUpjtxpEyqUqtPc30wEg/rO9vmKmqKoLPT37svc2NV
# BmGNl+85qO4fV/w7Cx7J0Bbqk19KcRNdjt6eKoTnTPHBHlVHQIHZpMxacbFOAkJr
# qAVkYZdz7ikNXTxV+GRb36tC4ByMNxE2DF7vFdvaiZP0CVZ5ByJ2gAhXMdK9+usx
# zVk913qKde1OAuWdv+rndqkAIm8fUlRnr4saSCg7cIbUwCCf116wUJ7EuJDg0vHe
# yhnCeHnBbyH3RZkHEi2ofmfgnFISJZDdMAeVZGVOh20Jp50XBzqokpPzeZ6zc1/g
# yILNyiVgE+RPkjnUQshd1f1PMgn3tns2Cz7bJiVUaqEO3n9qRFgy5JuLae6UweGf
# AeOo3dgLZxikKzYs3hDMaEtJq8IP71cX7QXe6lnMmXU/Hdfz2p897Zd+kU+vZvKI
# 3cwLfuVQgK2RZ2z+Kc3K3dRPz2rXycK5XCuRZmvGab/WbrZiC7wJQapgBodltMI5
# GMdFrBg9IeF7/rP4EqVQXeKtevTlZXjpuNhhjuR+2DMt/dWufjXpiW91bo3aH6Ea
# jOALXmoxgltCp1K7hrS6gmsvj94cLRf50QQ4U8Q wggd6MIIFYqADAgECAgphDpDS
# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEA nnqH
# tDyYUFaVAkvAK0eqq6nhoL95SZQu3RnpZ7tdQ89QR3++7A+4hrr7V4xxmkB5BObS
# 0YK+MALE02atjwWgPdpYQ68WdLGroJZHkbZdgERG+7tETFl3aKF4KpoSaGOskZXp
# TPnCaMo2PXoAMVMGpsQEQswimZq3IQ3nRQfBlJ0PoMMcN/+Pks8ZTL1BoPYsJpok
# t6cql59q6CypZYIwgyJ892HpttybHKg1ZtQLUlSXccRMlugPgEcNZJagPEgPYni4
# b11snjRAgf0dyQ0zI9aLXqTxWUU5pCIFiPT0b2wsxzRqCtyGqpkGM8P9GazO8eao
# mVItCYBcJSByBx/pS0cSYwBBHAZxJODUqxSXoSGDvmTfqUJXntnWkL4okok1FiCD
# Z4jpyXOQunb6egIXvkgQ7jb2uO26Ow0m8RwleDvhOMrnHsupiOPbozKroSa6paFt
# VSh89abUSooR8QdZciemmoFhcWkEwFg4spzvYNP4nIs193261WyTaRMZoceGun7G
# CT2Rl653uUj+F+g94c63AhzSq4khdL4HlFIP2ePv29smfUnHtGq6yYFDLnT0q/Y+
# Di3jwloF8EWkkHRtSuXlFUbTmwr/lDDgbpZiKhLS7CBTDj32I0L5i532+uHczw82
# oZDmYmYmIUSMbZOgS65h797rj5JJ6OkeEUJoAVw wggd6MIIFYqADAgECAgphDpDS
# AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK
# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0
# IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0
@ -977,55 +1262,55 @@ Say "Installation finished"
# xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96
# eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7
# r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I
# RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIVZ DCCFWA CAQEwgZUwfjELMAkG
# RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIVZ zCCFWM CAQEwgZUwfjELMAkG
# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z
# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAA YdyF3IVWUDHCQAAAAABh zAN
# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAA d9r8C6Sp0q00AAAAAAB3 zAN
# BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor
# BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQg pT/bxWwe
# aW0EinKMWCAzDXUjwXkIHldYzR6lw4/1Pc0 wQgYKKwYBBAGCNwIBDDE0MDKgFIAS
# BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQg JROF4V78
# d/qQulLV5Z+ncgFZgk9r0UoE37o5jTCDpSo wQgYKKwYBBAGCNwIBDDE0MDKgFIAS
# AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN
# BgkqhkiG9w0BAQEFAASCAQ CHd7sSQVq0YDg8QDx6/kLWn3s6jtvvIDCCgsO9spHM
# quPd4FPbG67DCsKDClekQs52qrtRO3Zo+JMnCw4j3bS+gZHzeJr2shbftOrpsFoD
# l7OPcUmtrqul9dkQCOp8t0MP3ls0n96/YyNy6lz4BAlTdkdDx957uAxalKaCIBzb
# R9QyppOKIfNFvwD4EI5KI6tpmSy/uH8SrRg7ZExAYZl6J6R18WkL7KHn649lPoAQ
# ujwrIXH10xOJops45ILGzKWQcHmCzLJGYapL4VHUuK+73nT+9ZROGHdk/PyvIcdw
# iERa+C06v305t3DA+CuHFy1tvyw7IFF6RVbLZPwxrJjToYIS7jCCEuo GCisGAQQB
# gjcDAwExghL aMIIS1gYJKoZIhvcNAQcCoIISxzCCEsM CAQMxDzANBglghkgBZQME
# BgkqhkiG9w0BAQEFAASCAQ B74lkh+M6W7qWNERtX5/xMFrSgaVCptxuBlBl93FN3
# aQJiCaToMeDXG3Nsf/GhIFCBz4fReYrMmZg5pmjs+d8s1dgXz2oOWVwx6bhnzdXS
# ce5dMqkUCzvN4QeJxTIhpeXsHwupWVbuqeTo5DdZHouTi4UFzgM0/K+sSbRI/FEe
# rS/vxtMbrtMz57kKjB/Z86dKJeDxQydKSapL/YIamfmYx26rjpXJqEs7W+FVRJwK
# nNNT0OGt7tdkL6k+7XQtK3f5yUqKMdTlmPyZ73z69tAtJclkIFC3liFVTMAf4MK+
# nheQal7OPNth86h4Lek3E19n2hrABTUeW2cLZ2WWEspFoYIS8TCCEu0 GCisGAQQB
# gjcDAwExghL dMIIS2QYJKoZIhvcNAQcCoIISyjCCEsY CAQMxDzANBglghkgBZQME
# AgEFADCCAVUGCyqGSIb3DQEJEAEEoIIBRASCAUAwggE8AgEBBgorBgEEAYRZCgMB
# MDEwDQYJYIZIAWUDBAIBBQAEI OCaTmvM1AP0WaEVqzKaaCu/R+bTlR4kCrM/ZXsb
# /eNOAgZgGeLsMwsYEzIwMjEwMjAzMjExNzQ5LjU5M VowBIACAfSggdSkgdEwgc4x
# MDEwDQYJYIZIAWUDBAIBBQAEI EIDAx5adVXZRJeNOj9JW7M03Sl8XvjtY9M98TvW
# cUwSAgZgieWmNfwYEzIwMjEwNTE5MTcwMDI4LjY0O VowBIACAfSggdSkgdEwgc4x
# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1p
# Y3Jvc29mdCBPcGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMg
# VFNTIEVTTj o4OTdBLUUzNTYtMTcwM TElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUt
# U3RhbXAgU2VydmljZaCCDk EwggT1MIID3aADAgECAhMzAAABLCKvRZd1+Rvu AAAA
# AA Es MA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo
# VFNTIEVTTj pEOURFLUUzOUEtNDNGR TElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUt
# U3RhbXAgU2VydmljZaCCDk QwggT1MIID3aADAgECAhMzAAABYfWiM16gKiRp AAAA
# AA Fh MA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo
# aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y
# cG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEw
# MB4XDT E5MTIxOTAxMTUwM1oXDTIxMDMxNzAxMTUwM1 owgc4xCzAJBgNVBAYTAlVT
# MB4XDT IxMDExNDE5MDIyMVoXDTIyMDQxMTE5MDIyMV owgc4xCzAJBgNVBAYTAlVT
# MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK
# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVy
# YXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTj o4OTdB
# LUUz NTYtMTcwM TElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vydmlj
# ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBA PK1zgSSq+MxAYo3qpCt
# QDxSMPPJy6mm/wfEJNjNUnYtLFBwl1BUS5trEk/t41ldxITKehs+ABxYqo4Qxsg3
# Gy1ugKiwHAnYiiekfC+ZhptNFgtnDZIn45zC0AlVr/6UfLtsLcHCh1XElLUHfEC0
# nBuQcM/SpYo9e3l1qY5NdMgDGxCsmCKdiZfYXIu+U0UYIBhdzmSHnB3fxZOBVcr5
# htFHEBBNt/rFJlm/A4yb8oBsp+Uf0p5QwmO/bCcdqB15JpylOhZmWs0sUfJKlK9E
# rAhBwGki2eIRFKsQBdkXS9PWpF1w2gIJRvSkDEaCf+lbGTPdSzHSbfREWOF9wY3i
# Yj8CAwEAAaOCARswggEXMB0GA1UdDgQWBBRRahZSGfrCQhCyIyGH9DkiaW7L0 zAf
# YXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTj pEOURF
# LUUz OUEtNDNGR TElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vydmlj
# ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBA JeInahBrU//GzTqhxUy
# AC8UXct6UJCkb2xEZKV3gjggmLAheBrxJk7tH+Pw2tTcyarLRfmV2xo5oBk5pW/O
# cDc/n/TcTeQU6JIN5PlTcn0C9RlKQ6t9OuU/WAyAxGTjKE4ENnUjXtxiNlD/K2ZG
# MLvjpROBKh7TtkUJK6ZGWw/uTRabNBxRg13TvjkGHXEUEDJ8imacw9BCeR9L6und
# r32tj4duOFIHD8m1es3SNN98Zq4IDBP3Ccb+HQgxpbeHIUlK0y6zmzIkvfN73Zxw
# fGvFv0/Max79WJY0cD8poCnZFijciWrf0eD1T2/+7HgewzrdxPdSFockUQ8QovID
# IYkCAwEAAaOCARswggEXMB0GA1UdDgQWBBRWHpqd1hv71SVj5LAdPfNE7PhLL zAf
# BgNVHSMEGDAWgBTVYzpcijGQ80N7fEYbxTNoWoVtVTBWBgNVHR8ETzBNMEugSaBH
# hkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNU
# aW1TdGFQQ0FfMjAxMC0wNy0wMS5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUF
# BzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1RpbVN0
# YVBDQV8yMDEwLTA3LTAxLmNydDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsG
# AQUFBwMIMA0GCSqGSIb3DQEBCwUAA4IBAQ BPFxHIwi4vAH49w9Svmz6K3tM55RlW
# 5pPeULXdut2Rqy6Ys0+VpZsbuaEoxs6Z1C3hMbkiqZFxxyltxJpuHTyGTg61zfNI
# F5n6RsYF3s7IElDXNfZznF1/2iWc6uRPZK8rxxUJ/7emYXZCYwuUY0XjsCpP9pbR
# RKeJi6r5arSyI+NfKxvgoM21JNt1BcdlXuAecdd/k8UjxCscffanoK2n6LFw1PcZ
# lEO7NId7o+soM2C0QY5BYdghpn7uqopB6ixyFIIkDXFub+1E7GmAEwfU6VwEHL7y
# 9rNE8bd+JrQs+yAtkkHy9FmXg/PsGq1daVzX1So7CJ6nyphpuHSN3VfT MIIGcTCC
# AQUFBwMIMA0GCSqGSIb3DQEBCwUAA4IBAQ AQTA9bqVBmx5TTMhzj+Q8zWkPQXgCc
# SQiqy2YYWF0hWr5GEiN2LtA+EWdu1y8oysZau4CP7SzM8VTSq31CLJiOy39Z4RvE
# q2mr0EftFvmX2CxQ7ZyzrkhWMZaZQLkYbH5oabIFwndW34nh980BOY395tfnNS/Y
# 6N0f+jXdoFn7fI2c43TFYsUqIPWjOHJloMektlD6/uS6Zn4xse/lItFm+fWOcB2A
# xyXEB3ZREeSg9j7+GoEl1xT/iJuV/So7TlWdwyacQu4lv3MBsvxzRIbKhZwrDYog
# moyJ+rwgQB8mKS4/M1SDRtIptamoTFJ56Tk6DuUXx1JudToelgjEZPa5 MIIGcTCC
# BFmgAwIBAgIKYQmBKgAAAAAAAjANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMC
# VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV
# BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJv
@ -1060,36 +1345,36 @@ Say "Installation finished"
# cs0d9LiFAR6A+xuJKlQ5slvayA1VmXqHczsI5pgt6o3gMy4SKfXAL1QnIffIrE7a
# KLixqduWsqdCosnPGUFN4Ib5KpqjEWYw07t0MkvfY3v1mYovG8chr1m1rtxEPJdQ
# cdeh0sVV42neV8HR3jDA/czmTfsNv11P6Z0eGTgvvM9YBS7vDaBQNdrvCScc1bN+
# NR4Iuto229Nfj950iEkSoYIC zzCCAjg CAQEwgfyhgdSkgdEwgc4xCzAJBgNVBAYT
# NR4Iuto229Nfj950iEkSoYIC 0jCCAjs CAQEwgfyhgdSkgdEwgc4xCzAJBgNVBAYT
# AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBP
# cGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTj o4
# O TdBLUUzNTYtMTcwM TElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vy
# dmljZaIjCgEBMAcGBSsOAwIaAxUA DE5OKSMoNx/mYxYWap1RTOohbJ2 ggYMwgYCk
# cGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTj pE
# O URFLUUzOUEtNDNGR TElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vy
# dmljZaIjCgEBMAcGBSsOAwIaAxUA FW5ShAw5ekTEXvL/4V1s0rbDz3m ggYMwgYCk
# fjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD
# Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIF
# AO PFChkwIhgPMjAyMTAyMDMxNTQwMDlaGA8yMDIxMDIwNDE1NDAwOVowdDA6 Bgor
# BgEEAYRZCgQBMS wwKjAKAgUA48UKGQIBADAHAgEAAgIXmDAHAgEAAgIRyTAKAgUA
# 48ZbmQ IBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAID
# B6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAHeeznL2n6HWCjHH94Fl
# hcdW6TEXzq4XNgp1Gx1W9F8gJ4x+SwoV7elJZkwgGffcpHomLvIY/VSuzsl1NgtJ
# TWM2UxoqSv58BBOrl4eGhH6kkg8Ucy2tdeK5T8cHa8pMkq2j9pFd2mRG/6VMk0dl
# Xz7Uy3Z6bZqkcABMyAfuAaGbMYIDDTCCAwkCAQEwgZMwfDELMAkGA1UEBhMCVVMx
# EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT
# FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUt
# U3RhbXAgUENBIDIwMTACEzMAAAEsIq9Fl3X5G+4AAAAAASwwDQYJYIZIAWUDBAIB
# B QCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQx
# IgQg/QYv7yp+354WTjWUIsXWndTEzXjaYjqwYjcBxCJKjdUwgfoGCyqGSIb3DQEJ
# EAIvMYHqMIHnMIHkMIG9BCBbn/0uFFh42hTM5XOoKdXevBaiSxmYK9Ilcn9nu5ZH
# 4T CBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw
# DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x
# JjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABLCKv
# RZd1+RvuAAAAAAEsMCIEIIfIM3YbzHswb/Kj/qq1l1cHA6QBl+gEXYanUNJomrpT
# MA0GCSqGSIb3DQEBCwUABIIBAAwdcXssUZGO7ho5+NHLjIxLtQk543aKGo+lrRMY
# Q9abE1h/AaaNJl0iGxX4IihNWyfovSfYL3L4eODUBAu68tWSxeceRfWNsb/ZZfUi
# v89hpLssI/Gf1BEgNMA4zCuIGQiC8okusVumEpAhhvCEbSiTTTtBdolTnU/CAKui
# oxaU3R9XkKh1F4oAM26+dJ1J2BLQXPs5afNvvedDsZWNQUPK1sFF3JRfzxiTrwBW
# EJRyflev9gyDoqCHzippgb+6+eti1WTkcA9Q49GIT11S6LOAVqkSC9N7Nqf8ksh8
# ARdwT8jigpsm+mj7lrVU9upDkhVYhKeO8oiZq95Q53Zkteo =
# AO RPamMwIhgPMjAyMTA1MTkxNDQzNDdaGA8yMDIxMDUyMDE0NDM0N1owdzA9 Bgor
# BgEEAYRZCgQBMS 8wLTAKAgUA5E9qYwIBADAKAgEAAgIYCAIB/zAHAgEAAgIRJjAK
# AgUA5FC74w IBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIB
# AAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAEP3zVlXXAn4O1Ms
# 68s11f0LWnsKutmWLnJls7YN9alFuA+jJcq/S8x2VoJAWAZTdWtdT5N7Gf/BeTAe
# 8D0krUvAYkKN9sIFxBsV9Zum88+HNP6X3yn+CD+ZzOlhtqvgG+fuuRXPutLZfLc/
# BMw0pVKop8ty4t9o1C5cghIH1n8uMYIDDTCCAwkCAQEwgZMwfDELMAkGA1UEBhMC
# VVMx EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV
# BAoT FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp
# bWUtU3RhbXAgUENBIDIwMTACEzMAAAFh9aIzXqAqJGkAAAAAAWEwDQYJYIZIAWUD
# B AIBB QCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0B
# CQQxIgQgYzAzV5OthXnPmIpD3kPIVmwz+sGvwSbjTEW5rOqHhyUwgfoGCyqGSIb3
# DQEJEAIvMYHqMIHnMIHkMIG9BCBhz4un6mkSLd/zA+0N5YLDGp4vW/VBtNW/lpmh
# tAk4bz CBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u
# MRAw DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp
# b24x JjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAB
# YfWiM16gKiRpAAAAAAFhMCIEIArbvJb5j55rDAQa7Rx5K7mjnxUY6RgiRY1AROOp
# m2rLMA0GCSqGSIb3DQEBCwUABIIBAFS544uO7FOimzTwMDkFNhMT7GmZBc9L2wDF
# EjcDlHvcdELdWpqa8Au6rCdhW6618btwdFqR7fkNMH7F0TrY1ktOae5fZUaybIRV
# EMWAAqXLkVyePlssQamjt1+BYvxzYFh3T5JBr2R/rzaGJIck49r1cEsLBV0JaSQT
# QKiOsR+QEbSCNWXQaq/koJrKR5Ugro0y4SmSejnOj5+1/4PlTolFoJAM4pIiT2A1
# uMs5f219BvkwyRmF32z9EpYQvBdoGpT65DQDuZQ5F6wV1Ph4H7yOzarcdnwPohT+
# BeH2jrcR3BMAxC3umgRUmTxnzPsoq9FJuRTyHCNygGn+VMImNfk =
# SIG # End signature block