gists, net, build comments edit

I saw a tweet come across asking how to get the OS version in MSBuild. MSBuild will automatically import any environment variables… but it appears the OS version isn’t an environment variable, so it doesn’t have any OS version info you can get out of the box.

You can, however, do a registry key lookup. Here’s a quick MSBuild snippet showing how to get the Windows version out of the registry. If you want more version-related information, there’s a lot in the registry at HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion.

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="DisplayVersion" xmlns="">
    <OsVersion>$(registry:HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion@CurrentVersion).$(registry:HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion@CurrentBuildNumber)</OsVersion>
  <Target Name="DisplayVersion">
    <Message Text="Version: $(OsVersion)" />

Granted, it would be kind of nice to have this out of the box, but at least you don’t have to write a whole custom task for it.

net comments edit

Let’s say you have a Windows service written in .NET that you got from a third party. It doesn’t really matter what it does - maybe it monitors something or responds to web service requests or something. And let’s say it works really well and does everything you need it to do… except this one little thing way down the stack is misbehaving.

You’ve done your homework - you’ve used Reflector and found exactly what the problem is, and it’s just a small thing - maybe it reads from a fixed configuration location and you need it to read from somewhere else. Maybe it throws an exception because it isn’t handling errors right. Whatever it might be, you have this boxed service that would be perfect for your needs if only this one thing could be fixed.

So what do you do? One option:Typemock Isolator.

WARNING: What I’m going to show you may make you feel a little weird. You may intially think “it’s wrong” or something. But as you’re thinking this, consider - what if this could save you a year of development time? What if it could save you a ton of QA time in testing every function of the service and allow you to focus only on the code path you’ve changed? From a pragmatic standpoint, would it be worth it?

ADDITIONAL WARNING: If you actually do this, it’s all at your own risk. Seriously. It’s all you, baby. “Works on my machine!”

Normally you’d think of Typemock Isolator as a testing tool. But its ability to run via the profiler API and substitute in behavior for just about anything makes it far more useful than just testing. For example, there’s an aspect-oriented programming framework called CThru out on CodePlex that uses this functionality. In our case, we can use Isolator to fix up the problematic behavior in the boxed service. Here’s how you do it:

Set up a service account that will have Typemock Isolator enabled on it. You’ll want this to be a separate user account that doesn’t do anything else because you’re going to globally enable Typemock Isolator on any process that account runs. You probably don’t actually want that on anything except this service you’re going to fix up, so make it a dedicated account. You’ll need to make sure this account has permissions to run as a service and has all the permissions it needs to run the boxed service - like if it reads from a certain file location, the account will need those rights. You’ll get an “Access Denied” error if you don’t set this up right.

Set the environment for the service account. To enable Typemock Isolator, you’ll need to set a couple of environment variables. Run regedit as the service user: runas /user:MACHINENAME\username "regedit" Make sure you don’t already have regedit open or this won’t work. (It only allows one instance to run at a time.) Now navigate to the HKEY_CURRENT_USER\Environment key and add two string (REG_SZ) values:

  • Cor_Enable_Profiling = 0x1
  • COR_PROFILER = {B146457E-9AED-4624-B1E5-968D274416EC}

Yes, they look like numbers, but make sure they’re string values. Setting those two environment variables will make it so any process that user account runs will have Typemock Isolator enabled.

Create a Windows service application. You’ll be using the main entry point (Program class), but eventually won’t need the actual Windows service. The Windows service in your wrapper project is helpful because it makes it easier to create an installer.

Add references. You will, at a minimum, need to reference the .exe file that has the boxed service’s Main method. If the malfunctioning component is in a different assembly, you’ll need to reference that, too.

Set up expectations and call the boxed service’s Main method. Use Typemock Isolator to replace the problem code with code you want to run, then just let the boxed service execute as usual. Your Program class will probably look something like this:

public static class Program
  public static void Main()

  public static void ExpectationSetup()
    ReplacementComponent replacement = new ReplacementComponent();
    MalfunctioningComponent fake = new MalfunctioningComponent();

Create a service installer. Open up your Windows service class in the designer. In the Properties window, give your service a name - this is what the user will see in the Services control panel. Now right-click on the designer for the service - the background of the designer, not any components that may be there - and select “Add Installer.” This will add a class called “ProjectInstaller” to your wrapper application.

Set the installer properties. Open the “ProjectInstaller” class in design view. You should see a two components on the designer surface: “serviceInstaller1” and “serviceProcessInstaller1.”

  • Select ”serviceInstaller1.” In the Properties window, check the ServiceName to ensure it’s what you want folks to see in the Services control panel (it should have taken the name from your Windows service). Also set the StartType to be what you want - Automatic, Manual, or Disabled.
  • Select “serviceProcessInstaller1.” In the Properties window, set the Account property to “User.”
  • Right-click the designer surface of “ProjectInstaller” and select “View Code.” In the ProjectInstaller constructor, just after the call to “InitializeComponent,” update serviceProcessInstaller1 with the username and password for the service account you created. This will make it easier to install; otherwise you have to manually go in and set this later.

The constructor of ProjectInstaller will look like this:

public ProjectInstaller()
  this.serviceProcessInstaller1.Password = "password";
  this.serviceProcessInstaller1.Username = @"MACHINENAME\username";

Delete the Windows service from your project. You only really needed this to make it easy to create the installer. It doesn’t do anything and you don’t need it.

Build the service wrapper and place the executable in the same folder as the boxed service. The reason you want it in the same folder as the boxed service is because when you pass control on to the boxed service, it’s going to need to find all of its dependencies and such. Rather than try to fight it into some other place, just stick that tiny .exe you just built into the folder with the boxed service.

Stop/disable the boxed service. If the service you’re wrapping is installed, you need to stop and disable it. You can uninstall it if you want, but you’re going to basically be running a different copy of the service and you don’t want two running.

Use InstallUtil to install your service wrapper. With the installer class you made, it’s simple: installutil MyServiceWrapper.exe (Obviously you need to use the name of your service wrapper .exe file there.) If you ever need to uninstall, it’s just as simple: installutil /u MyServiceWrapper.exe

Start your service and watch the magic happen. Typemock Isolator will replace the behavior you specified, just like it does in a unit testing environment, but it’ll do it in a regular Windows service runtime environment. You may need to do some additional work if your boxed service is really complex, but it’ll work. (For example, if the boxed service, BoxedService.exe, has a configuration file, BoxedService.exe.config, you’ll need to copy that for use by your wrapped service  - MyServiceWrapper.exe.config or whatever. That way the .NET configuration system will work… but that sort of tweak will be specific to the boxed service you’re wrapping.)

HOLD THE PHONE. What’s the performance impact? Honestly, I don’t know. You’ll have to measure a before-and-after on your own system and make your own call. You’ll probably also want to balance that out against how much time something like this will save you, etc. It’s all trade-offs, right?

SAMPLE CODE! WE WANT A SAMPLE! I created a little sample so you can see what this looks like. In the solution, you’ll find two projects - “BoxedService,” which has a malfunctioning component in it that we want to fix; and “ServiceWrapper,” which has the Isolator expectation setup that fixes the behavior. Both of these services write to Trace so you’ll want to have DebugView so you can watch the trace output without having to fight with the debugger. Debugging a Windows service is painful.

If you install the BoxedService, you’ll see an error message get periodically written to Trace; uninstall that and install the ServiceWrapper (running under an account that has Isolator enabled) and you’ll see the problem behavior get replaced.

[Download (20K)]

My grandma, Jeanne Ann Illig: 1922 -
2009A couple of weeks ago, on June 11, my paternal grandmother passed away. She had been having some age-related health problems for a while, so it wasn’t a surprise, but it was still a sad loss.

We lived next door to my grandparents when I was a kid and visited them a lot. There was a path cut from our backyard to theirs so we could get there without walking along the road. It feels like it wasn’t that long ago where she was out playing baseball with us out there. I loved her a lot and those are some great memories I’ll have with me always.

Grandma was actually a very talented artist. My family has some amazing pencil drawings she did as a young lady. She didn’t pursue it into her later years, but she always encouraged us kids to follow our artistic passions.

From her obituary:

Jeanne Illig, 86, of Milwaukie, passed away Thursday, June 11, 2009. She was born on Oct. 1, 1922, in Minneola, Long Island, NY, to Maurice John and Jeanette (Jahelka) Rethen.

She worked as a long distance operator prior to marriage. She married Carl Illig on Nov. 4, 1944, at Mitchel Field in Long Island.

Jeanne moved to Oregon in 1952; lived in Estacada for 34 years, at Summerplace for 10 years, and has lived in Milwaukie since 2001. She loved square dancing and was a member of the Record Breakers Square Dance Club. She also enjoyed ceramic painting and artwork.

The B-52s play the Oregon Zoo. Yes, this is a horrible picture. Trust
me, it's
them.Jenn and I went on a little adventure on Friday night and saw The B-52s live at the Oregon Zoo. The zoo has a pretty awesome concert series going this year and we figured since we’d never been to a concert at the zoo before, this would be a good one to start with.

The tickets let us into the zoo at 4:00p, the doors to the amphitheater opened at 5:00p, and the show started at 7:00p. We got there about 4:30p and the line was already super long, so I guess now we know - get there at 4:00p. We still ended up getting decent seats - not awesome, but decent - about halfway back.

The only real problem was the rain. Between, say, 5:00p and 7:15p it was raining like a torrential downpour, so Jenn and I were sitting on these little lawn chairs we brought, huddled under a blue plastic tarp, sucking down a $25 pizza and a $6 drink. Not a big deal since the opening band, The 88, was okay… but not awesome. (It reminded us a little of the Paul and Storm song “Opening Band.”)

Then The B-52s came out and the rain stopped (or, at least, kept to a very, very light drizzle), and people stood up and danced. As much as you can “dance” in the middle of a soaked-out zoo amphitheater, that is, so it was more standing and bobbing up and down. But there was definitely movement.

They totally rocked. I’m a latecomer to the whole B-52s thing, so the stuff I’m most familiar with is off the Cosmic Thing album and a few of the radio hits. They played some that I wasn’t familiar with but liked a lot so I ended up doing a little Amazon spree to get a few of the earlier albums. Kate Pierson still has it and is still one of my favorite voices, and Fred Schneider with his unmistakeable sprechgesang style is just fantastic.

Their part of the show ran, oh, maybe an hour and a half, then they were done, but it was a great 90 minutes. Hearing “Love Shack” and “Rock Lobster” live was worth the price of admission. “Knock a little louder, Portland!”

media, windows comments edit

I was noticing some of the disk access on my Windows Home Server was running a bit sluggish and I thought about how usually when this happens on other computers, I’ll run a defrag… but since Windows Home Server has a different filesystem, you can’t really just do a stanard defrag, can you?

Turns out, there are Windows Home Server defrag products.

The two that seem to be the most popular are PerfectDisk 10 and Diskeeper 2009. Both of those have WHS-specific versions that integrate nicely with the WHS console and understand that filesystem. There’s a great head-to-head review of these products over at We Got Served. The end result? It’s a tie - they are comparable products.

I ended up choosing PerfectDisk based on the price point. It costs just over half of what Diskeeper costs ($50 vs. $80) and I found this coupon code (SUMMERFUN20 - expires June 30) over at Philip Churchill’s site that got me $10 off that so I’ve got WHS defrag for $40. Can’t beat that.

UPDATE 1/26/2010: I noticed after about a couple of weeks of PerfectDisk for WHS use that I was getting health warnings every three or four days on my WHS system disk. At first I thought I was going to have to replace the disk, but on a hunch I disabled defragmentation of the system drive. While the warnings on the system drive stopped, I did get a warning on another drive, so I disabled PerfectDisk on the WHS entirely. Since then I haven’t gotten any disk health warnings. I’ve run all the disks through extensive diagnostics so I have to blame PerfectDisk for the warnings. I’m going to post to their user community and see if anyone else is having the same issue, but in the meantime, YMMV.

UPDATE 2/5/2010: I’ve started talking with PerfectDisk support about the issues I’m seeing. I’ll keep updates running on the explanatory blog entry.