Build/InstallHelpers.ps1
function Install-MSI { Param ( [String]$MsiUrl, [String]$MsiName ) $exitCode = -1 try { Write-Host "Downloading $MsiName..." $FilePath = "${env:Temp}\$MsiName" Invoke-WebRequest -Uri $MsiUrl -OutFile $FilePath $Arguments = ('/i', $FilePath, '/QN', '/norestart' ) Write-Host "Starting Install $MsiName..." $process = Start-Process -FilePath msiexec.exe -ArgumentList $Arguments -Wait -PassThru $exitCode = $process.ExitCode if ($exitCode -eq 0 -or $exitCode -eq 3010) { Write-Host -Object 'Installation successful' return $exitCode } else { Write-Host -Object "Non zero exit code returned by the installation process : $exitCode." exit $exitCode } } catch { Write-Host -Object "Failed to install the MSI $MsiName" Write-Host -Object $_.Exception.Message exit -1 } } function Install-EXE { Param ( [String]$Url, [String]$Name, [String[]]$ArgumentList ) $exitCode = -1 try { Write-Host "Downloading $Name..." $FilePath = "${env:Temp}\$Name" Invoke-WebRequest -Uri $Url -OutFile $FilePath Write-Host "Starting Install $Name..." $process = Start-Process -FilePath $FilePath -ArgumentList $ArgumentList -Wait -PassThru $exitCode = $process.ExitCode if ($exitCode -eq 0 -or $exitCode -eq 3010) { Write-Host -Object 'Installation successful' return $exitCode } else { Write-Host -Object "Non zero exit code returned by the installation process : $exitCode." return $exitCode } } catch { Write-Host -Object "Failed to install the Executable $Name" Write-Host -Object $_.Exception.Message return -1 } } function Stop-SvcWithErrHandling { <# .DESCRIPTION Function for stopping the Windows Service with error handling .AUTHOR Andrey Mishechkin v-andmis@microsoft.com .PARAMETER -ServiceName The name of stopping service .PARAMETER -StopOnError Switch for stopping the script and exit from PowerShell if one service is absent #> param ( [Parameter(Mandatory, ValueFromPipeLine = $true)] [string] $ServiceName, [Parameter()] [switch] $StopOnError ) Process { $Service = Get-Service $ServiceName -ErrorAction SilentlyContinue if (-not $Service) { Write-Warning "[!] Service [$ServiceName] is not found"; if ($StopOnError) { exit 1; } } else { Write-Host "Try to stop service [$ServiceName]"; try { Stop-Service -Name $ServiceName -Force; $Service.WaitForStatus("Stopped", "00:01:00"); Write-Host "Service [$ServiceName] has been stopped successfuly"; } catch { Write-Error "[!] Failed to stop service [$ServiceName] with error:" $_ | Out-String | Write-Error; } } } } function Set-SvcWithErrHandling { <# .DESCRIPTION Function for setting the Windows Service parameter with error handling .AUTHOR Andrey Mishechkin v-andmis@microsoft.com .PARAMETER -ServiceName The name of stopping service .PARAMETER -Arguments Hashtable for service arguments #> param ( [Parameter(Mandatory, ValueFromPipeLine = $true)] [string] $ServiceName, [Parameter(Mandatory)] [hashtable] $Arguments ) Process { $Service = Get-Service $ServiceName -ErrorAction SilentlyContinue if (-not $Service) { Write-Warning "[!] Service [$ServiceName] is not found"; } try { Set-Service $ServiceName @Arguments; } catch { Write-Error "[!] Failed to set service [$ServiceName] arguments with error:" $_ | Out-String | Write-Error; } } } function Start-DownloadWithRetry { param ( [Parameter(Mandatory)] [string] $Url, [Parameter(Mandatory)] [string] $Name, [string] $DownloadPath = "${env:Temp}", [int] $Retries = 20 ) $FilePath = Join-Path -Path $DownloadPath -ChildPath $Name #Default retry logic for the package. while ($retries -gt 0) { try { Write-Host "Downloading package from: $Url to path $FilePath ." (New-Object System.Net.WebClient).DownloadFile($Url, $FilePath) break } catch { Write-Host "There is an error during package downloading:`n $_" $retries-- if ($retries -eq 0) { Write-Host "File can't be downloaded. Please try later or check that file exists by url: $Url" exit 1 } Write-Host "Waiting 30 seconds before retrying. Retries left: $retries" Start-Sleep -Seconds 30 } } return $FilePath } function Install-VsixExtension { Param ( [string] $Url, [Parameter(Mandatory = $true)] [string] $Name, [string] $FilePath, [Parameter(Mandatory = $true)] [string] $VSversion, [int] $retries = 20, [switch] $InstallOnly ) if (!$InstallOnly) { $FilePath = Start-DownloadWithRetry -Url $Url -Name $Name } $ArgumentList = ('/quiet', "`"$FilePath`"") Write-Host "Starting Install $Name..." try { #There are 2 types of packages at the moment - exe and vsix if ($Name -match "vsix") { $process = Start-Process -FilePath "C:\Program Files (x86)\Microsoft Visual Studio\$VSversion\Enterprise\Common7\IDE\VSIXInstaller.exe" -ArgumentList $ArgumentList -Wait -PassThru } else { $process = Start-Process -FilePath ${env:Temp}\$Name /Q -Wait -PassThru } } catch { Write-Host "There is an error during $Name installation" $_ exit 1 } $exitCode = $process.ExitCode if ($exitCode -eq 0 -or $exitCode -eq 1001) { # 1001 means the extension is already installed Write-Host "$Name installed successfully" } else { Write-Host "Unsuccessful exit code returned by the installation process: $exitCode." exit 1 } #Cleanup downloaded installation files if (!$InstallOnly) { Remove-Item -Force -Confirm:$false $FilePath } } function Get-VSExtensionVersion { param ( [string] [Parameter(Mandatory = $true)] $packageName ) $instanceFolders = Get-ChildItem -Path "C:\ProgramData\Microsoft\VisualStudio\Packages\_Instances" if ($instanceFolders -is [array]) { Write-Host "More than one instance installed" exit 1 } $stateContent = Get-Content -Path (Join-Path $instanceFolders.FullName '\state.packages.json') $state = $stateContent | ConvertFrom-Json $packageVersion = ($state.packages | Where-Object { $_.id -eq $packageName }).version if (!$packageVersion) { Write-Host "installed package $packageName for Visual Studio 2019 was not found" exit 1 } return $packageVersion } function Get-ToolcachePackages { $toolcachePath = Join-Path $env:ROOT_FOLDER "toolcache.json" Get-Content -Raw $toolcachePath | ConvertFrom-Json } function Get-ToolsByName { param ( [Parameter(Mandatory = $True)] [string]$SoftwareName ) (Get-ToolcachePackages).PSObject.Properties | Where-Object { $_.Name -match $SoftwareName } | ForEach-Object { $packageNameParts = $_.Name.Split("-") [PSCustomObject] @{ ToolName = $packageNameParts[1] Versions = $_.Value Architecture = $packageNameParts[3, 4] -join "-" } } } function Get-WinVersion { (Get-WmiObject -class Win32_OperatingSystem).Caption } function Test-IsWin19 { (Get-WinVersion) -match "2019" } function Test-IsWin16 { (Get-WinVersion) -match "2016" } |