InstallVisualStudio.ps1 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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 ($Passive -and $Quiet) {
  35. Write-Host -ForegroundColor Red "Error: The -Passive and -Quiet options cannot be used together."
  36. Write-Host -ForegroundColor Red "Run ``Get-Help $PSCommandPath`` for more details."
  37. exit 1
  38. }
  39. $ErrorActionPreference = 'Stop'
  40. Set-StrictMode -Version 1
  41. $intermedateDir = "$PSScriptRoot\obj"
  42. mkdir $intermedateDir -ErrorAction Ignore | Out-Null
  43. $bootstrapper = "$intermedateDir\vsinstaller.exe"
  44. $ProgressPreference = 'SilentlyContinue' # Workaround PowerShell/PowerShell#2138
  45. Invoke-WebRequest -Uri "https://aka.ms/vs/16/release/vs_$($Edition.ToLowerInvariant()).exe" -OutFile $bootstrapper
  46. $responseFile = "$PSScriptRoot\vs.json"
  47. if ("$Edition" -eq "BuildTools") {
  48. $responseFile = "$PSScriptRoot\vs.buildtools.json"
  49. }
  50. $channelId = (Get-Content $responseFile | ConvertFrom-Json).channelId
  51. $productId = "Microsoft.VisualStudio.Product.$Edition"
  52. if (-not $InstallPath) {
  53. $vsWhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
  54. if (Test-Path $vsWhere)
  55. {
  56. $installations = & $vsWhere -version '[16,17)' -format json -sort -prerelease -products $productId | ConvertFrom-Json
  57. foreach ($installation in $installations) {
  58. Write-Host "Found '$($installation.installationName)' in '$($installation.installationPath)', channel = '$($installation.channelId)'"
  59. if ($installation.channelId -eq $channelId) {
  60. $InstallPath = $installation.installationPath
  61. break
  62. }
  63. }
  64. }
  65. }
  66. if (-not $InstallPath) {
  67. $InstallPath = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\$Edition"
  68. }
  69. # no backslashes - this breaks the installer
  70. $InstallPath = $InstallPath.TrimEnd('\')
  71. [string[]] $arguments = @()
  72. if (Test-path $InstallPath) {
  73. $arguments += 'modify'
  74. }
  75. $arguments += `
  76. '--productId', $productId, `
  77. '--installPath', "`"$InstallPath`"", `
  78. '--in', "`"$responseFile`"", `
  79. '--norestart'
  80. if ($Passive) {
  81. $arguments += '--passive'
  82. }
  83. if ($Quiet) {
  84. $arguments += '--quiet', '--wait'
  85. }
  86. Write-Host
  87. Write-Host "Installing Visual Studio 2019 $Edition" -f Magenta
  88. Write-Host
  89. Write-Host "Running '$bootstrapper $arguments'"
  90. foreach ($i in 0, 1, 2) {
  91. if ($i -ne 0) {
  92. Write-Host "Retrying..."
  93. }
  94. $process = Start-Process -FilePath "$bootstrapper" -ArgumentList $arguments -ErrorAction Continue -PassThru `
  95. -RedirectStandardError "$intermedateDir\errors.txt" -Verbose -Wait
  96. Write-Host "Exit code = $($process.ExitCode)."
  97. if ($process.ExitCode -eq 0) {
  98. break
  99. } else {
  100. # https://docs.microsoft.com/en-us/visualstudio/install/use-command-line-parameters-to-install-visual-studio#error-codes
  101. if ($process.ExitCode -eq 3010) {
  102. Write-Host -ForegroundColor Red "Error: Installation requires restart to finish the VS update."
  103. break
  104. }
  105. elseif ($process.ExitCode -eq 5007) {
  106. Write-Host -ForegroundColor Red "Error: Operation was blocked - the computer does not meet the requirements."
  107. break
  108. }
  109. elseif (($process.ExitCode -eq 5004) -or ($process.ExitCode -eq 1602)) {
  110. Write-Host -ForegroundColor Red "Error: Operation was canceled."
  111. }
  112. else {
  113. Write-Host -ForegroundColor Red "Error: Installation failed for an unknown reason."
  114. }
  115. Write-Host
  116. Write-Host "Errors:"
  117. Get-Content "$intermedateDir\errors.txt" | Write-Warning
  118. Write-Host
  119. Get-ChildItem $env:Temp\dd_bootstrapper_*.log |Sort-Object CreationTime -Descending |Select-Object -First 1 |% {
  120. Write-Host "${_}:"
  121. Get-Content "$_"
  122. Write-Host
  123. }
  124. $clientLogs = Get-ChildItem $env:Temp\dd_client_*.log |Sort-Object CreationTime -Descending |Select-Object -First 1 |% {
  125. Write-Host "${_}:"
  126. Get-Content "$_"
  127. Write-Host
  128. }
  129. $setupLogs = Get-ChildItem $env:Temp\dd_setup_*.log |Sort-Object CreationTime -Descending |Select-Object -First 1 |% {
  130. Write-Host "${_}:"
  131. Get-Content "$_"
  132. Write-Host
  133. }
  134. }
  135. }
  136. Remove-Item "$intermedateDir\errors.txt" -errorAction SilentlyContinue
  137. exit $process.ExitCode