I’ve recently been working on a Visual Studio extension that acts a bit like the Visual Studio memory window, but visualises the memory as a texture. Like the memory window, there’s a box for the user to type in an address expression. The plug-in then needs to evaluate the expression in the context of the debugger’s current thread and stack frame, and then retrieve the contents of the debuggee process’s memory space at that address.

This is a relatively common operation for the debugger — it’s done by the memory window, as well as the watch windows, of course. I therefore assumed it would be fairly straightforward. I was very wrong. After much hair-pulling, however, I was finally able to get it to work, so I thought I’d document it here in case anyone else needs to do something similar.

It’s worth noting that the plug-in I’m writing is written in C#, so all the code snippets will be C# too. The VSX API is COM, though, so the steps should be basically the same whatever the language. And I’m targeting VS 2012, so all of this may or may not work with other versions. The API doesn’t look to have changed between 2010 and 2012, so there’s a good chance it will work there, but I haven’t tried it.

Evaluating Expressions

The Visual Studio automation API provides a way to evaluate expressions in the current stack frame (EnvDTE.DTE.Debugger.GetExpression), which is of course exactly what we want. However, the returned type doesn’t allow direct access to the debuggee’s memory, just the evaluated value as a string.

So, we need to use the full ‘package’ VSX API. The main interface that represents a property in the debugger in the VSX API is IDebugProperty2. Once you have one of these, you can fairly easily use it to get the contents of the debuggee’s memory. To get an IDebugProperty2, you can call IDebugExpression2.EvaluateSync. You can get an IDebugExpression2 by calling ParseText on an IDebugExpressionContext2 interface. And you can get one of those by calling GetExpressionContext on an IDebugStackFrame2. So the challenge becomes to get an IDebugStackFrame2 presenting the ‘current’ stack frame — i.e. the one that is used to evaluate watch expressions.

Registering for Debug Events

Despite much searching, I couldn’t find a way in the VSX API to directly get the current stack frame (or the current thread, or even the current process, for that matter). However, there is a way to register for debug events, which enables the caller to receive a callback when the state of the debugger changes, including, for example, hitting a breakpoint. And the callback takes as parameters various interfaces representing the new state of the debugger.

This is achieved by implementing the IDebugEventCallback2 interface, and then passing it to IVsDebugger.AdviseDebugEventCallback. This method takes an object (IUnknown in the underlying COM gubbins), but it will magically be cast to an IDebugEventCallback2 underneath. Needless to say, this took me some time to realise! Anyway, here’s some code that does this.

The debugger indicates an event by calling the Event method of the IDebugEventCallback2 interface. The parameters include the GUID of the event that has fired, along with a load of interfaces representing the state of the debugger. I needed an event that gets fired when you hit a breakpoint (or the debugger breaks for some other reason, like an exception), and also when the user changes the stack frame or thread. Fortunately there is one event that covers all these scenarios. Its GUID is {ce6f92d3-4222-4b1e-830d-3ecff112bf22}, but I have no idea what event it represents — I could find no mention of it in the docs or on Google. But it gets fired at just the right time, so I’m not going to lose much sleep over that!

Getting the Current Stack Frame

Unfortunately, the parameters to IDebugEventCallback2.Event do not include the current stack frame (that would be too easy!) It does give you the current thread (as IDebugThread2), though. With this, you can enumerate all the stack frames for that thread using the EnumFrameInfo method. This still gives you no information about what the current stack frame is, however.

Fortunately, we can get this information from the automation API. EnvDTE.DTE.Debugger.CurrentStackFrame returns a StackFrame object. This in and of itself isn’t much use to us, but the object is actually an instance of StackFrame2 (obviously!) So, casting to this type, we can get its Depth property, which indicates how deep in the stack the current frame is. It’s worth noting that the top frame has a depth of 1, not 0. Here’s some code to do all that.

So, we now have a way of enumerating the stack frames of the current thread, and we know the depth the current frame, so it’s simple to put these two together and get the current stack frame. Here’s a bit more code that does just that.