MDbg and the managed wrappers around ICorDebug only work on .NET 2.0 (VS2005). I previously discussed why they won't work on 1.1. One workaround to access ICorDebug from managed code in .NET 1.1 is to use MC++. In general, MC++ can be extremely useful for gluing managed and unmanaged code together.
Using MC++:MC++ will let you easily create a bunch of real managed objects that wrap the com-classic ICorDebug. This lets you control exactly how you're using ICorDebug, including how you're using IUnknown, and thus work around the the issues with COM-interop on ICorDebug in 1.1.
This beats out alternative ideas such as:- creating your own COM-object to wrap ICorDebug and then using COM-interop to import that. - using a lot of P/ invokes and native wrappers to access ICorDebug.Both of these involve larger wrapper layers. Using MC++ here lets you avoid an extra component, and COM-interop altogether. We use MC++ for the native disassembly view in the SDK MDbg (mdbgdis.dll).
Fitting into application model:I think the MC++ model here fits well into many Application's models:1. Debuggers commonly wrap ICorDebug objects with their own classes to add additional functionality. (MDbg, VS, Cordbg all do this). Thus you can just make those wrappers be in MC++.2. In a GUI app, you're going to have some STA UI thread that needs to make a cross thread call to access ICorDebug (which is MTA) and then get the data back to the UI thread to to do stuff like fill out some listbox for a callstack with frames. This sets up a natural boundary. The code that fills out the listbox can just be written in MC++. Or you could have some small MC++ glue to just read the data from ICorDebug and then give it back to some C# that actually fills out the listbox. The rest of the GUI can be some managed code, such as winforms app.
One testimony that it works: Claudiu Codreanu (from Starlims) tried out this technique and found it to work very well.
Code examples:
Here's an example of part of a MC++ class wrapper for ICorDebugThread. It's using the new VS2005 MC++ syntax, but you can do the same things with the old VS2003 MC++ syntax.
// Managed MC++ class to wrap it. public ref class ThreadWrapper { public: // Method int GetId() { DWORD id; HRESULT hr = m_thread->GetID(&id); System::Runtime::InteropServices::Marshal::ThrowExceptionForHR(hr); return id; } // Above as a property property int Id { int get() { return GetId(); } } // add other methods of interest // Raw pointer to COM-classic interface from ICorDebug ICorDebugThread * m_thread; // Could have additional data // (or we could put that data in a derived class) };
C# can then access that class just like any other class. For example:
void PrintThread(ThreadWrapper t) { Console.WriteLine("Thread's ID is: " + t.Id); }