Loading Visual Studio 2005\.NET 2.0 SDK Tools (vsvars32.bat) in Monad (MSH)

Scott Hanselman’s recent zeal for MSH has motivated me to take another look at Monad.

I saw the original Jeffrey Snover Channel 9 video and downloaded the beta then; he just about drop kicks you with his enthusiasm, so I had to try it. My first two co-op terms (internships is another term) were spent as a system administrator, so there will always be a soft spot for a powerful command line\scripting platform in my heart. So I took a look, played around, saw that it was WAY too much to learn, and quickly dropped it. Now that Scott has extolled the virtues of Monad in recordable audio format, I figured I’d give it another try.

Scott’s right when he says it’s rough to start with; there definitely is a learning curve and I don’t think I’m out of the dark yet. But I’ve decided to take the first steps by customizing the bejeezus out of it. The first thing I wanted to do was start every instance with the VS/.NET SDK tools set up. I’m not a huge command line guy in my day-to-day work, but I tend to use the .NET SDK tools when I do. So it would be more convenient to load them every time I run MSH.

You, of course, know the “Visual Studio Command Prompt” menu option in the Visual Studio Tools start menu group is merely a call to cmd.exe with a batch file loaded. Well, I figured my first task would be to rewrite that as a msh script (although not strictly necessary – at least, I think – I figured it was a good place to start scripting), then set it be called whenever I start an instance of msh.exe.

So that’s what I did.

See ya.

Why aren’t you leaving?

Oh alright.

The first part, writing the script, was pretty easy. I opened TextPad with a new document and opened the vsvars32.bat file (located in “%PROGRAMFILES%\Microsoft Visual Studio 8\Common7\Tools”) side by side and started converting.

The file in its entirety is provided below. Download it here. It’s not a very complex script and certainly doesn’t take advantage of the power of the msh script engine, but I still took away a lot from doing this script. First, I forgot what a pain in the ass it is to debug scripts if you’re just learning the syntax. I’m sure once I get going, I’ll be more productive with this, but typos really killed me.

I really like setting variables in msh. You’ll note the syntax for setting variables in different scopes makes it very clear to read. For example, $env:Path is the %PATH% environment variable; $script:tools sets the tools variable for the whole script. One gotcha that I’m not used to is that functions have to be declared before they’re used. I know that dates me as a young’un, but whatever, so I’m not old enough to use C so much. JScript and VBScript don’t have that restriction, and that’s where I’ve done most of my scripting. Another thing I like is variable expansion. If you embed the variable name in a string, msh will expand it for you. That’s very handy for writing file paths as you’ll note below. I put in a few different ways of doing it, just because.

The second part of the problem is to load this for every msh.exe instance. I could do what MS does for the Windows SDK and a have a shortcut that calls msh.exe with some command line arguments, notably the script, but that would mean I have to open every instance from the same shortcut; that’s inconvenient, especially if you’re used to, like I am, opening it up from the Run dialog. The best way to do this for my needs (yours may differ) was to set it up in my profile.msh file located at “My Documents\msh\profile.msh”. This is a place for users to set their own preferences for the shell. I found this post about calling multiple msh scripts from profile.msh but it didn’t quite work for me. I set a variable to the full path of the vsvars32.msh file location and then called . $vsvars, which loads the script for me. I think that’s a unix shell command – the ‘.’ – but it’s been so long since I’ve used unix, so I don’t know. Run gacutil or xsd and watch in churn out the usage message. Sweet, huh?

# vsvars32.msh
# This is a re-write of the vsvars32.bat file that is
# installed by Visual Studio 2005. I did this to learn
# msh script. Your mileage may vary. This is not supported.

$script:VsInstall = "${env:ProgramFiles}\Microsoft Visual Studio 8"
$script:tools = "$script:VsInstall\Common7\Tools"
$script:vc = "$script:VsInstall\VC"

$env:VSINSTALLDIR = $script:VsInstall
$env:VCINSTALLDIR = $script:vc
$env:FrameworkDir = "${env:windir}\Microsoft.NET\Framework"
$env:FrameworkVersion = "v2.0.50727"
$env:FrameworkSDKDir = $script:VsInstall + "\SDK\v2.0"

write-host "Setting environment for using Microsoft Visual Studio 2005 x86 tools."

$env:DevEnvDir = $script:VsInstall + "\Common7\IDE"
$script:FxDir = $env:FrameworkDir + "\" + $env:FrameworkVersion

# ------------------------------------------------------------------
# Prepend a directory to a semi-colon delimited list of directories
# I stole this function from the SetEnv.msh script provided by the Windows SDK
# ------------------------------------------------------------------
function PrependToVar
{
param ([string]$list, [string]$newdir)
	return "$newDir;$list"
}

$Path = PrependToVar $env:Path $env:DevEnvDir
$Path = PrependToVar $Path "$script:vc\bin"
$Path = PrependToVar $Path $script:tools
$Path = PrependToVar $Path "$script:tools\bin"
$Path = PrependToVar $Path "$script:vc\PlatformSDK\bin"
$Path = PrependToVar $Path "$env:FrameworkSDKDir\bin"
$Path = PrependToVar $Path $script:FxDir
$Path = PrependToVar $Path "$script:vc\VCPackages"

$Include = PrependToVar $Include "$script:vc\atlmfc\include"
$Include = PrependToVar $Include "$script:vc\INCLUDE"
$Include = PrependToVar $Include "$script:vc\PlatformSDK\INCLUDE"
$Include = PrependToVar $Include "$script:FrameworkSDKDir\INCLUDE"

$Lib = PrependToVar $Lib "$script:vc\atlmfc\lib"
$Lib = PrependToVar $Lib "$script:vc\lib"
$Lib = PrependToVar $Lib "$script:vc\platformsdk\lib"
$Lib = PrependToVar $Lib "$script:FrameworkSDKDir\lib"

$env:Path = $script:Path
$env:Include = $script:Include
$env:Lib = $script:Lib
$env:LibPath = "$script:FxDir;$script:vc\atlmfc\lib"

Project Codenames Should Be Fun

Recently, at work, we started using project code names. The theme for the code names is mountains.

Gee, I wonder where they got that idea from.

What’s the whole point of a codename? I think it’s to refer to a product release without getting all confused about version numbers. There is nothing saying they have to be plain and boring. You can say, “Were the bugs y and z fixed for the latest beta release of Lava Lamp?” Now, what’s wrong with that? Lava lamps are fun and mysterious. It would make the app you’re working on more fun to work on, especially if it’s “themware”.

My favourite themes are probably ‘80s cartoons characters. What about Project She-Ra? Or Project Megatron? Now that’s a server I don’t want to mess with; its security must be hard to get through.

Actually, anything from the ‘80s works. How about ‘80s rock divas? Project Benatar has a nice ring to it. ‘80s movies? Project Porky’s for version 1, Porky’s Revenge for version 2.

Got any ideas for good project codename themes?

Now playing: Odds – Satisfied

Update: Fixed some grammatical errors that were bugging my mom. 🙂 Thanks, mom.

What does the rest of blogspace say about Version Numbers?

Searching the internet for version numbers is largely pointless: the hits are useless. I’ve tried variations on “version numbers daily build.”

However, I, in my voracious blog reading, remembered a few posts by some bloggers I read so I figured I’d link to them here so they are all in one spot.

  • Jensen Harris’ post explaining Office build numbers. This post is only a couple of weeks old at the time of this post. The Office team uses a date-based build number.
  • The next was the hardest to find because I know he posted about it; turns out he talked about it in the context of another subject, where I thought it was a specific post on the boring subject of version numbers. Wesner Moise has a quick breakdown of CLR version numbers. So quick I’ll quote it here:

    Longhorn use version 2.0.31113.25 of the CLR, whereas the CTP is a much more recent build, 2.0.40301.9. The third number is the build number. It likely indicates the day the build was made (under the format YMMDD). The last number most likely reflects the number of attempts made to stabilize that build. That Longhorn’s 25 is almost triple that of the CTP’s 9 is a good indication of how much more stable Longhorn’s earlier version of the CLR is compared to the CTP. The PDC build used build 30703, which had been prepared for months before PDC.

  • The last link I found was the most appropriate to my query: Suzanne Cook, who unfortunately looks like she stopped blogging last year, has a post on what to do with internal builds versus external builds. She is in the latter camp, it appears. 

Now playing: Headstones – Tiny Teddy

Why Would You Want An Always-Increasing Version Number?

This is a follow up to my last post about version numbers.

There’s a very practical reason for having a monotonically increasing Version Number as a function of time: upgrading installers. If your daily build produces an executable including an upgrading installer, then you definitely want an increasing build number for every daily build. The example in the last post did not have this requirement, but that doesn’t negate that it’s a very good, practical reason to add complexity to the build process.

The benefit you get from an upgrading installer is that when installing the latest and greatest daily build, you don’t have to uninstall the last version. That’s about the extent of my installer knowledge (and the wording I used is probably grossly inaccurate, but who’s going to correct me?).

This requirement is probably only valid if you release an installer. I don’t have much experience with web apps, but my guess is that they are updated in a far less formal manner; the requirement for version numbers for daily builds is not as important. For component developers, released components should definitely have version numbers – that’s just about the only way to determine which one you have. But internal daily builds for components? I’m not convinced you need them.

Now playing: Headstones – Whatchagonnado

Version Numbers

This is a uber-geeky. You are warned.

Version numbers consist of four numbers at their most complex: Major.Minor.Revision.Build. They’re very important, especially when you have multiple releases in the wild. They let you track what code is running on the users machine, so if they have a version that contains a bug, you can tell if it’s a new bug, or if it has been fixed in a later release.

Suppose you were part of a software team that writes components which other teams in the company use to create products. Suppose you release fairly often and the possibility that you may have to support multiple versions of the same library, and may even continue releasing multiple versions.

Let’s say you have ComponentX.dll whose latest version is 1.6.7.0. The next release is a bug fix release with no added functionality, so the next version released is 1.6.8.0. Once version 1.6.8.0 is released, there will be a branch release, 1.6.8.1, and the next bug fix release, 1.6.9.0. A further release on the 1.6.8.1 branch is required; it will be 1.6.8.2.

Starting to see the pattern?

OK, now what if your team were to impose a daily build with this versioning scheme?

One of you wants to increment the build number on every build; this creates havoc for the system above, so you must come up with an intricate set of rules to govern version numbers that requires lots of lost time to explain the whole system. Another thinks the daily builds shouldn’t be versioned at all, because once the daily build is institute, he’s going to bring continuous integration into the mix. This would potentially mean several builds a day, that really only reflect the health of the code in the repository; they’re throwaway builds that will never be released.

What do you do for your builds at your shop? Whose side would you be on?

Now playing: The Philosopher Kings – Last Stand