InstallVisualStudio.ps1 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. <#
  2. .SYNOPSIS
  3. Installs or updates Visual Studio on a local developer machine.
  4. .DESCRIPTION
  5. This installs Visual Studio along with all the workloads required to contribute to this repository.
  6. .PARAMETER Edition
  7. Selects which 'offering' of Visual Studio to install. Must be one of these values:
  8. BuildTools
  9. Community
  10. Professional
  11. Enterprise (the default)
  12. .PARAMETER InstallPath
  13. The location on disk where Visual Studio should be installed or updated. Default path is location of latest
  14. existing installation of the specified edition, if any. If that VS edition is not currently installed, default
  15. path is '${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\`$Edition".
  16. .PARAMETER Passive
  17. Run the installer without requiring interaction.
  18. .PARAMETER Quiet
  19. Run the installer without UI and wait for installation to complete.
  20. .LINK
  21. https://visualstudio.com
  22. https://github.com/aspnet/AspNetCore/blob/master/docs/BuildFromSource.md
  23. .EXAMPLE
  24. To install VS 2019 Enterprise, run this command in PowerShell:
  25. .\InstallVisualStudio.ps1
  26. #>
  27. param(
  28. [ValidateSet('BuildTools','Community', 'Professional', 'Enterprise')]
  29. [string]$Edition = 'Enterprise',
  30. [string]$InstallPath,
  31. [switch]$Passive,
  32. [switch]$Quiet
  33. )
  34. if ($env:TF_BUILD) {
  35. Write-Error 'This script is not intended for use on CI. It is only meant to be used to install a local developer environment. If you need to change Visual Studio requirements in CI agents, contact the @aspnet/build team.'
  36. exit 1
  37. }
  38. if ($Passive -and $Quiet) {
  39. Write-Host -ForegroundColor Red "Error: The -Passive and -Quiet options cannot be used together."
  40. Write-Host -ForegroundColor Red "Run ``Get-Help $PSCommandPath`` for more details."
  41. exit 1
  42. }
  43. $ErrorActionPreference = 'Stop'
  44. Set-StrictMode -Version 1
  45. $intermedateDir = "$PSScriptRoot\obj"
  46. mkdir $intermedateDir -ErrorAction Ignore | Out-Null
  47. $bootstrapper = "$intermedateDir\vsinstaller.exe"
  48. $ProgressPreference = 'SilentlyContinue' # Workaround PowerShell/PowerShell#2138
  49. Invoke-WebRequest -Uri "https://aka.ms/vs/16/release/vs_$($Edition.ToLowerInvariant()).exe" -OutFile $bootstrapper
  50. $responseFile = "$PSScriptRoot\vs.json"
  51. if ("$Edition" -eq "BuildTools") {
  52. $responseFile = "$PSScriptRoot\vs.buildtools.json"
  53. }
  54. $channelId = (Get-Content $responseFile | ConvertFrom-Json).channelId
  55. $productId = "Microsoft.VisualStudio.Product.$Edition"
  56. if (-not $InstallPath) {
  57. $vsWhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
  58. if (Test-Path $vsWhere)
  59. {
  60. $installations = & $vsWhere -version '[16,17)' -format json -sort -prerelease -products $productId | ConvertFrom-Json
  61. foreach ($installation in $installations) {
  62. Write-Host "Found '$($installation.installationName)' in '$($installation.installationPath)', channel = '$($installation.channelId)'"
  63. if ($installation.channelId -eq $channelId) {
  64. $InstallPath = $installation.installationPath
  65. break
  66. }
  67. }
  68. }
  69. }
  70. if (-not $InstallPath) {
  71. $InstallPath = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\$Edition"
  72. }
  73. # no backslashes - this breaks the installer
  74. $InstallPath = $InstallPath.TrimEnd('\')
  75. [string[]] $arguments = @()
  76. if (Test-path $InstallPath) {
  77. $arguments += 'modify'
  78. }
  79. $arguments += `
  80. '--productId', $productId, `
  81. '--installPath', "`"$InstallPath`"", `
  82. '--in', "`"$responseFile`"", `
  83. '--norestart'
  84. if ($Passive) {
  85. $arguments += '--passive'
  86. }
  87. if ($Quiet) {
  88. $arguments += '--quiet', '--wait'
  89. }
  90. Write-Host
  91. Write-Host "Installing Visual Studio 2019 $Edition" -f Magenta
  92. Write-Host
  93. Write-Host "Running '$bootstrapper $arguments'"
  94. foreach ($i in 0, 1, 2) {
  95. if ($i -ne 0) {
  96. Write-Host "Retrying..."
  97. }
  98. $process = Start-Process -FilePath "$bootstrapper" -ArgumentList $arguments -ErrorAction Continue -PassThru `
  99. -RedirectStandardError "$intermedateDir\errors.txt" -Verbose -Wait
  100. Write-Host "Exit code = $($process.ExitCode)."
  101. if ($process.ExitCode -eq 0) {
  102. break
  103. } else {
  104. # https://docs.microsoft.com/en-us/visualstudio/install/use-command-line-parameters-to-install-visual-studio#error-codes
  105. if ($process.ExitCode -eq 3010) {
  106. Write-Host -ForegroundColor Red "Error: Installation requires restart to finish the VS update."
  107. break
  108. }
  109. elseif ($process.ExitCode -eq 5007) {
  110. Write-Host -ForegroundColor Red "Error: Operation was blocked - the computer does not meet the requirements."
  111. break
  112. }
  113. elseif (($process.ExitCode -eq 5004) -or ($process.ExitCode -eq 1602)) {
  114. Write-Host -ForegroundColor Red "Error: Operation was canceled."
  115. }
  116. else {
  117. Write-Host -ForegroundColor Red "Error: Installation failed for an unknown reason."
  118. }
  119. Write-Host
  120. Write-Host "Errors:"
  121. Get-Content "$intermedateDir\errors.txt" | Write-Warning
  122. Write-Host
  123. Get-ChildItem $env:Temp\dd_bootstrapper_*.log |Sort-Object CreationTime -Descending |Select-Object -First 1 |% {
  124. Write-Host "${_}:"
  125. Get-Content "$_"
  126. Write-Host
  127. }
  128. $clientLogs = Get-ChildItem $env:Temp\dd_client_*.log |Sort-Object CreationTime -Descending |Select-Object -First 1 |% {
  129. Write-Host "${_}:"
  130. Get-Content "$_"
  131. Write-Host
  132. }
  133. $setupLogs = Get-ChildItem $env:Temp\dd_setup_*.log |Sort-Object CreationTime -Descending |Select-Object -First 1 |% {
  134. Write-Host "${_}:"
  135. Get-Content "$_"
  136. Write-Host
  137. }
  138. }
  139. }
  140. Remove-Item "$intermedateDir\errors.txt" -errorAction SilentlyContinue
  141. exit $process.ExitCode