Software Mechanics
Why do we even have that lever?

The last vsvars32.ps1 I'll ever need

January 14, 2008 15:25 by Chris

By now, I hope I don't need to sell folks on Windows Powershell. It's a fantastic command line environment once you get used to it, and I love using it.  However, for the .NET developer, there's the standard set of command line utilities (sn.exe, gacutil, ildasm, etc. ad nauseum) which only work properly once you've run the vsvars32.bat file that ships with Visual Studio.

When Powershell was first released, there was a bunch of people who scrambled to translate vsvars32.bat into vsvars32.ps1, the equivalent Powershell script. And now that VS 2008 is out, the process is repeating itself. The best current version was posted recently by Brad Wilson. While this approach worked, the duplication of effort always bothered me. The batch file just sets a bunch of environment variables, and Powershell will run .bat files, but unfortunately it runs them in a child shell. Which means they set the environment variable in the child shell, which promptly goes away, taking the variables with it. Darn.

The translation route seemed like the only option, but it just rubbed me the wrong way. What happens when a service pack updates the batch file? Then we have to re-translate. Or another release of VS? Argh, more mindless work.

The ultimate solution came to me while I was reading Bruce Payette's fantastic book, Windows Powershell in Action. Buried in there is this very nice little function:

function Get-Batchfile ($file) {
    $cmd = "`"$file`" & set"
    cmd /c $cmd | Foreach-Object {
        $p, $v = $_.split('=')
        Set-Item -path env:$p -value $v
    }
}

What does this do? Basically, it runs the .bat or .cmd file you give it in a child shell, then runs the 'set' command in that shell to dump out the environment. Then it parses the resulting output, and sticks those environment variables into the powershell environment. This way, you can run any batch file and get the environment variables set. Just what we need!

This was part of the way there. I also wanted some easy way to run vsvars32 specifically, as I end up doing that a lot. Looking around, I found that VS 2005 and VS 2008 store their install path in a very predictable spot in the registry. The only only difference is a version number: 8.0 for 2005, 9.0 for 2008. A little more hacking, and I got this function:

function VsVars32($version = "8.0")
{
    $key = "HKLM:SOFTWARE\Microsoft\VisualStudio\" + $version
    $VsKey = get-ItemProperty $key
    $VsInstallPath = [System.IO.Path]::GetDirectoryName($VsKey.InstallDir)
    $VsToolsDir = [System.IO.Path]::GetDirectoryName($VsInstallPath)
    $VsToolsDir = [System.IO.Path]::Combine($VsToolsDir, "Tools")
    $BatchFile = [System.IO.Path]::Combine($VsToolsDir, "vsvars32.bat")
    Get-Batchfile $BatchFile
    [System.Console]::Title = "Visual Studio " + $version + " Windows Powershell"
}

Having this in my profile lets me type "vsvars32" and I'll be set up with my VS 2005 environment, or "vsvars32 9.0" and I'll have a VS 2008 environment. I also had it update the window title so I can keep track of which environment I'm running in. Hopefully, if the VS team maintains their registry conventions when a patch or the next version of VS comes out, this script shouldn't need to change.

I hope these little  scripts help folks out there work better with Powershell and Visual Studio.


Currently rated 3.7 by 11 people

  • Currently 3.727273/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:
Categories: .NET
Actions: E-mail | Permalink | Comments (9) | Comment RSSRSS comment feed

Comments

Comments are closed