InstallVisualStudio.ps1 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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. [CmdletBinding(DefaultParameterSetName = 'Default')]
  28. param(
  29. [ValidateSet('BuildTools','Community', 'Professional', 'Enterprise')]
  30. [string]$Edition = 'Enterprise',
  31. [string]$InstallPath,
  32. [switch]$Passive,
  33. [switch]$Quiet
  34. )
  35. if ($Passive -and $Quiet) {
  36. Write-Host "The -Passive and -Quiet options cannot be used together." -f Red
  37. Write-Host "Run ``Get-Help $PSCommandPath`` for more details." -f Red
  38. exit 1
  39. }
  40. $ErrorActionPreference = 'Stop'
  41. Set-StrictMode -Version 1
  42. $intermedateDir = "$PSScriptRoot\obj"
  43. mkdir $intermedateDir -ErrorAction Ignore | Out-Null
  44. $bootstrapper = "$intermedateDir\vsinstaller.exe"
  45. $ProgressPreference = 'SilentlyContinue' # Workaround PowerShell/PowerShell#2138
  46. Invoke-WebRequest -Uri "https://aka.ms/vs/16/release/vs_$($Edition.ToLowerInvariant()).exe" -OutFile $bootstrapper
  47. $responseFile = "$PSScriptRoot\vs.json"
  48. if ("$Edition" -eq "BuildTools") {
  49. $responseFile = "$PSScriptRoot\vs.buildtools.json"
  50. }
  51. $channelId = (Get-Content $responseFile | ConvertFrom-Json).channelId
  52. $productId = "Microsoft.VisualStudio.Product.$Edition"
  53. if (-not $InstallPath) {
  54. $vsWhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
  55. if (Test-Path $vsWhere)
  56. {
  57. $installations = & $vsWhere -version '[16,17)' -format json -sort -prerelease -products $productId | ConvertFrom-Json
  58. foreach ($installation in $installations) {
  59. Write-Host "Found '$($installation.installationName)' in '$($installation.installationPath)', channel = '$($installation.channelId)'"
  60. if ($installation.channelId -eq $channelId) {
  61. $InstallPath = $installation.installationPath
  62. break
  63. }
  64. }
  65. }
  66. }
  67. if (-not $InstallPath) {
  68. $InstallPath = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\$Edition"
  69. }
  70. # no backslashes - this breaks the installer
  71. $InstallPath = $InstallPath.TrimEnd('\')
  72. [string[]] $arguments = @()
  73. if (Test-path $InstallPath) {
  74. $arguments += 'modify'
  75. }
  76. $arguments += `
  77. '--productId', $productId, `
  78. '--installPath', "`"$InstallPath`"", `
  79. '--in', "`"$responseFile`"", `
  80. '--norestart'
  81. if ($Passive) {
  82. $arguments += '--passive'
  83. }
  84. if ($Quiet) {
  85. $arguments += '--quiet', '--wait'
  86. }
  87. Write-Host ""
  88. Write-Host "Installing Visual Studio 2019 $Edition" -f Magenta
  89. Write-Host ""
  90. Write-Host "Running '$bootstrapper $arguments'"
  91. $process = Start-Process -FilePath "$bootstrapper" -ArgumentList $arguments `
  92. -PassThru -RedirectStandardError "$intermedateDir\errors.txt" -Verbose -Wait
  93. if ($process.ExitCode -ne 0) {
  94. Get-Content "$intermedateDir\errors.txt" | Write-Error
  95. }
  96. Remove-Item "$intermedateDir\errors.txt" -errorAction SilentlyContinue
  97. exit $process.ExitCode