Monday, 5 September 2011

Replacing Visual Studio Command Prompt

Working a lot with Visual Studio, I naturally wanted to be able to use Powershell as the preferred command line tool instead of cmd.exe that Visual Studio Command Prompt uses. Not being aware of the Invoke-Batchfile functionality available in Powershell Community Extensions, and seeing that the script logic could be made so much more efficient in Powershell, I ended up re-writing the whole script in Powershell.

One thing that simplified it for me was the fact that I only need the x64 variant, but it should be ver easy to extend this to cover all other variants. In fact, I started that but when I found that I didn't need them myself that part naturally got demoted... And it could surely be bettered some day.

Anyway, here's the script:
#vcvars64.ps1, for setting Visual Studio environment variables for 64-bit architecture
[CmdletBinding()]
param()

function Set-EnvVar
{
 param (
  [string]$Variable,
  [string]$Value,
  [switch]$Append
 )
 
 if ($Append)
 {
  if (Test-Path ('env:' + $Variable))
  {
   $Value = (Get-Item ('env:' + $Variable)).Value + ";$Value"
  }
 }
 
 [environment]::SetEnvironmentVariable($Variable, $Value)
}

function Set-EnvVarFromRegistry
{
 param (
  [string[]]$keys,
  [string]$property,
  [string]$environmentVariable,
  [string]$suffix,
  [switch]$append
 )
 
 foreach ($key in $keys)
 {
  if (Test-Path $key)
  {
   $regValue = (Get-ItemProperty $key).$property
   if (-not ($regValue -eq ""))
   {
    Set-EnvVar $environmentVariable ($regValue + $suffix)
    break
   }
  }
 }
}

Write-Host -ForegroundColor Yellow "Setting environment for using Microsoft Visual Studio 2010 x64 tools.`n"

$VSRegKeys32 = @("HKLM:\SOFTWARE\Microsoft\VisualStudio\SxS\VS7", "HKCU:\SOFTWARE\Microsoft\VisualStudio\SxS\VS7")
$VSRegKeys64 = @("HKLM:\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\SxS\VS7", "HKCU:\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\SxS\VS7")
$VSRegKeys = ($VSRegKeys32 + $VSRegKeys64)
$VCRegKeys32 = @("HKLM:\SOFTWARE\Microsoft\VisualStudio\SxS\VC7", "HKCU:\SOFTWARE\Microsoft\VisualStudio\SxS\VC7")
$VCRegKeys64 = @("HKLM:\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\SxS\VC7", "HKCU:\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\SxS\VC7")
$VCRegKeys = ($VCRegKeys32 + $VCRegKeys64)
$FSharpRegKeys = @("HKLM:\SOFTWARE\Microsoft\VisualStudio\10.0\Setup\F#", "HKCU:\SOFTWARE\Microsoft\VisualStudio\10.0\Setup\F#", "HKLM:\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\Setup\F#", , "HKCU:\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\Setup\F#")
$WindowsSDKRegKeys = @("HKLM:\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A", "HKCU:\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A")

Set-EnvVarFromRegistry $VSRegKeys "10.0" VS100COMNTOOLS "Common7\Tools\"
Set-EnvVarFromRegistry $VSRegKeys "10.0" VSINSTALLDIR
Set-EnvVarFromRegistry $VCRegKeys "10.0" VCINSTALLDIR
Set-EnvVarFromRegistry $FSharpRegKeys ProductDir FSHARPINSTALLDIR
Set-EnvVarFromRegistry $VCRegKeys64 FrameworkDir64 FrameworkDir
Set-EnvVarFromRegistry $VCRegKeys64 FrameworkVer64 FrameworkVersion
Set-EnvVar Framework35Version "v3.5"
Set-EnvVar VCbuildToolsPath ($env:VCINSTALLDIR + "VCPackages")

Set-EnvVarFromRegistry $WindowsSDKRegKeys InstallationFolder WindowsSdkDir
if ($env:WindowsSdkDir -eq "") { Set-EnvVar "WindowsSdkDir" "$env:VCINSTALLDIR\PlatformSDK\" }

if ($env:WindowsSdkDir)
{
 Set-EnvVar PATH ($env:WindowsSdkDir + "bin\NETFX 4.0 Tools\x64;" + $env:WindowsSdkDir + "bin\x64;" + $env:WindowsSdkDir + "bin") -Append
 Set-EnvVar INCLUDE ($env:WindowsSdkDir + "include") -Append
 Set-EnvVar LIB ($env:WindowsSdkDir + "lib\x64") -Append
}

# PATH
Set-EnvVar PATH ($env:VSINSTALLDIR + "Common7\Tools;" + $env:VSINSTALLDIR + "Common7\IDE;$($env:VCINSTALLDIR)VCPackages;$env:FrameworkDir\$env:FrameworkVersion;$env:FrameworkDir\$env:Framework35Version;" + $env:VCINSTALLDIR + "bin\amd64") -Append
if (Test-Path "$env:VSINSTALLDIR\Team Tools\Performance Tools\x64") { Set-EnvVar PATH ($env:VSINSTALLDIR + "Team Tools\Performance Tools\x64;" + $env:VSINSTALLDIR + "Team Tools\Performance Tools") -Append }
if (Test-Path "$env:ProgramFiles\HTML Help Workshop") { Set-EnvVar PATH "$env:ProgramFiles\HTML Help Workshop" -Append }
if (Test-Path "$env:ProgramFiles(x86)\HTML Help Workshop") { Set-EnvVar PATH "$env:ProgramFiles(x86)\HTML Help Workshop" -Append }
Write-Verbose "PATH set to $env:Path"

# INCLUDE
if (Test-Path "$env:VCINSTALLDIR\ATLMFC\INCLUDE") {Set-EnvVar INCLUDE ($env:VCINSTALLDIR + "ATLMFC\INCLUDE") -Append }
Set-EnvVar INCLUDE ($env:VCINSTALLDIR + "INCLUDE;") -Append
Write-Verbose "INCLUDE set to $env:INCLUDE"

# LIB
Set-EnvVar LIB ($env:VCINSTALLDIR + "LIB\amd64;") -Append
if (Test-Path "$env:VCINSTALLDIR\ATLMFC\LIB\amd64") {Set-EnvVar LIB ("$($env:VCINSTALLDIR)ATLMFC\LIB\amd64") -Append }
Write-Verbose "LIB set to $env:LIB"

# LIBPATH
Set-EnvVar LIBPATH ("$env:FrameworkDir\$env:FrameworkVersion;$env:FrameworkDir\$env:Framework35Version;$($env:VCINSTALLDIR)LIB\amd64") -Append
if (Test-Path "$env:VCINSTALLDIR\ATLMFC\LIB\amd64") {Set-EnvVar LIBPATH ($env:VCINSTALLDIR + "ATLMFC\LIB\amd64") -Append }
Write-Verbose "LIBPATH set to $env:LIBPATH"

Set-EnvVar Platform X64
Write-Verbose "Platform set to X64"
Set-EnvVar CommmandPromptType Native
Write-Verbose "CommmandPromptType set to Native"