home73k/priv/content/2020/08/2020-08-01_enable-vs-cli-env-in-ps.md

2.9 KiB

%{ title: "Enable Visual Studio CLI environment in PowerShell", date: ~N[2020-08-01 02:00:00], author: "Adam Piontek", tags: ["coding", "tech", "elixir", "windows", "powershell", "scripting"], }

My initial problem: I have an elixir project I'm building primarily on linux, but I want it to work on Windows, too, and I'm using bcrypt, which needs nmake to compile on Windows.

One must install Visual Studio (VS), but that's not enough. Your terminal/PowerShell CLI environment won't know about VS by default. VS includes batch files to set up a dev environment, but if you run them in PowerShell, they bring you into a CMD environment, which is no help if you want to use PowerShell.

Luckily, thanks to Michael Teter's blog, and posts on github that mentioned the VS Setup PS Module, I was able to put together a solution that works for me:

The built-in PowerShell (5.1 right now) will load a profile from (under user Documents folder): WindowsPowerShell\Microsoft.PowerShell_profile.ps1 — and PS 7 (pwsh.exe) will load its profile from the slightly different (under user Documents folder): PowerShell\Microsoft.PowerShell_profile.ps1

For each version where I want the environment set up, I place the following code in the profile:

function Invoke-CmdScript {
  param(
    [String] $scriptName 
  )
  $cmdLine = """$scriptName"" $args & set"
  & $Env:SystemRoot\system32\cmd.exe /c $cmdLine |
  select-string '^([^=]*)=(.*)$' | foreach-object {
    $varName = $_.Matches[0].Groups[1].Value
    $varValue = $_.Matches[0].Groups[2].Value
    set-item Env:$varName $varValue
  }
}

$installationPath  = (Get-VSSetupInstance -All | Select-Object InstallationPath).InstallationPath
$vcvars64Path = Join-Path -Path $installationPath -ChildPath "VC\Auxiliary\Build\vcvars64.bat"

if ($installationPath -and (Test-Path -Path $vcvars64Path)) {
  Invoke-CmdScript $vcvars64Path
}

As Michael explains:

The function allows you to run a script, the one that makes the build tools visible, but instead of losing the context after that script ends, the settings are propogated back to the calling shell (Powershell).

The profile then uses that Invoke-CmdScript function to call the vcvars64.bat script...

My addition is just to get the VS installation path from that VS Setup PS Module's Get-VSSetupInstance and build the script path from that. Hopefully that will survive future VS upgrades?