Essential Windows debugging tools

I’m no Windows dev expert, but I’ve been doing it long enough to have collected a set of tools that go with me. They sit in a nice little rectangle on my desktop, and I also have a USB key to carry them with. Not all people know about them though, or maybe have seen them and haven’t learned to use them. I recommend at least familiarity with the following:

  1. OleView I do a lot of COM work. I try to make it go away, but it keeps coming back. As such, my first choice of debugging tool is good old oleview. Every time our install breaks because of some munged dependency, the first step is to fire up oleview and check that all needed objects are registered, and that they can all be instantiated. That last bit is non-obvious but very cool – when you expand an object in the list and it turns bold, the object is actually being instantiated. So just expanding each one you care about is a good smoke test.
  2. Filemon Everybody probably knows this one already, but it’s so important that I can’t leave it out. If you haven’t used it, do yourself a favor and get familiar. It can be used for any program running on windows, so it’s good even for you Java folks. My strategy with Filemon is usually to first figure out a concise way to reproduce the problem, then do a specific session to see what’s happening. I usually forego the filters (remember the COM I’m running from? Lots of out-of-process servers there.) and just start/stop event logging at the right times.
  3. .NET Reflector Ah, what would we do without Lutz Roeder? I’ve used this to read my own (decompiled) code while working through a bug on a test machine. Saved me some walking back and forth at least, plus I felt like such an incredible badass doing it. It’s also good for determining that the localizer sent you back an assembly built with .NET 2.0, when you very clearly asked for 1.1. (A co-worker’s find, not my own)
  4. Spy++ Are you noticing a theme here? All the old tools that let us observe the bowels of the system are still useful. Sometimes you just want to watch the messages fly by, and Spy++ is still the way to do it. ManagedSpy may be worth a look too.

As mentioned above, what I find compelling and useful about these tools is that they take a step away from what your software is supposed to do (that’s what the source is for) and let you know what it’s actually doing. There’s an entire class of subtle bugs that such insight enables you to diagnose – the first two tools have saved my ass on multiple occasions.

Technorati Tags: , , ,

Easy C# Memoization

I called it MagicCache at first, thinking I’d come up with something new and cool! But, as usual, I’d actually just forgotten the name.

Memoization is a useful but intrusive technique. It’s the kind of thing that I want to be able to wield around my code and put it where I need it, almost as a configuration-time parameter. So I’m not quite satisfied with just writing the code myself each time I need it. This is a perfect case for AOP.

The approach I took was not to use an existing AOP framework, since I think that would freak my coworkers out a little, but rather to do my own simple system. It uses the fantastic DynamicProxy (as do all C# AOP systems I know of) to inject code, and I use a custom attribute to mark the invocations I care about. The result is quite pleasant to work with:

[Memoize]
virtual int Sum(int a, int b)
{
    return a+b;
}

Or, in more complicated cases:

[Memoize(MaxCount=100)]
virtual object BuildObject(string paramA, int paramB)
{
    ...
}

I like this particular method because the caching policy is nicely separated from the actual logic, but has enough proximity to see what’s going on. And I don’t have to write the caching code again and again, which means I’m free to enhance the general caching algorithm.

Of course it’s not quite as easy as all that. Memoized methods must be virtual, for DynamicProxy to be able to intercept the invocation, and the object in question must be wrapped in a proxy object. In my case I wrapped it all up in a single method call, Memoizer.CreateProxy(obj). For objects that are already built in a factory this is not problem at all, but sometimes it’s kind of inconvenient.

I’ve also added the ability to treat returned strings as paths to files which are deleted when they are removed from the cache, though I haven’t thought through it well enough to be generally useful.

Technorati Tags: , ,

mbUnit

I would like to take a moment to espouse the wonders of mbUnit. It is to NUnit as C++ is to C, as Perl is to Bourne shell, as Milk Duds are to milk. That is, the former supports the same basic principles as the latter, but gives you more rope with which to hang yourself. And really, who can resist that?

It supports the same "idiomatic" syntax as NUnit, which is a good start, since that's really the only way to do unit tests in C#. And you can do the usual TestFixture/Test stuff, which works, but is kind of clunky and unwieldy.

But the mbUnit folks have taken it a step further. The old way always involved writing cumbersome loops over sets of input and trying a particular call/assertion for each of them. Boring, repetitive, not ultimately traceable. But by allowing tests to have parameters and creating a configurable binding phase, all that goes away. It works like this:


[RowTest]
[Row(1,2)]
[Row(3,4)]
void TestSomething(int a, int b) { ...

That's just the binding, straight up, as a set of rows. Simple but useful, and far cleaner than the alternative. In the testrunner, you'll see that as two tests. This really is the right way to do it, I think, since you can easily trace failed tests to a particular set of inputs. But it really gets cool with CombinatorialTest. I find myself most often using the trivial case:


[Factory(typeof(string)]
public IEnumerable InputFiles()
{
return System.IO.Directory.GetFiles("inputDir");
}

[CombinatorialTest]
public MyTest( [UsingFactories("InputFiles")] string filename )
{ … }
Now that's downright great. And there are all kinds of other useful generators, like UsingValues and UsingLinear. With multiple parameters, Combinatorial test evidently combines them in some significant way, but I honestly don't understand the whole thing. I'm just willing to let it work.

My only complaint? I haven't yet found a good project template for visual studio. I'm sure I could make one, but my laziness is still fighting itself on that one. I know, it's supposed to be easier in VS2005, but my wounds have yet to heal from the last attempt.