My little pet project is actually called VSTorqueScript, so I’ve decided to use the correct title for my posts, too.
Today has been a somewhat productive day, although not as productive as I’ve hoped, because I was stuck with a very stupid issue for 3 or 4 hours. I’m not proud of it, but it made me go to the VSX forum and become active there.
I’ve worked more on the debug engine afterwards (well, actually I went jogging and swimming - in that order.. think about it) and made some progress. Quite a bit of the stub stuff is implemented now and I think I’ll start implementing the real thing tomorrow.
No screenshots this time, I’m sorry, but for the SDK users, I have a little helper file. If you look at the managed debug example, you’ll find an AD7Events file that wraps the debug event interfaces. I wasn’t easily able to port it over, so I decided to write my own version of it (while keeping the comments).
I’ve appended it to the post, if you want to take a look.
On other news I’ll probably switch this blog over to my own webspace soon to get some advantages (like expandable sourcecode amongst things), but I think I’ll stick to wordpress.com for a few more weeks. It’s really a pity that you can’t redirect from wordpress to your domain, but only vice-versa :(
Anyway, off to work some more on my code.
Cheers, Andreas
Here it is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.Debugger.Interop;
using Microsoft.VisualStudio;
namespace BlackHC.VSTorqueScript.DebugEngine
{
#region Event base classes
interface IEvent : IDebugEvent2
{
uint Attributes
{
get;
}
Guid IID{
get;
}
}
abstract class Event<ieventtype> : IEvent where IEventType : class
{
public Guid IID
{
get { return typeof(IEventType).GUID; }
}
public int GetAttributes(out uint eventAttributes)
{
= Attributes;
eventAttributes return VSConstants.S_OK;
}
public abstract uint Attributes
{
get;
}
}
class AsynchronousEvent<ieventtype> : Event<ieventtype> where IEventType : class
{
public override uint Attributes
{
get { return (uint)enum_EVENTATTRIBUTES.EVENT_ASYNCHRONOUS; }
}
}
class SynchronousEvent<ieventtype> : Event<ieventtype> where IEventType : class
{
public override uint Attributes
{
get { return (uint)enum_EVENTATTRIBUTES.EVENT_SYNCHRONOUS; }
}
}
class StoppingEvent<ieventtype> : Event<ieventtype> where IEventType : class
{
public override uint Attributes
{
get { return (uint)enum_EVENTATTRIBUTES.EVENT_ASYNC_STOP; }
}
}
#endregion
#region Event classes
/// <summary>
/// The debug engine (DE) sends this interface to the session debug manager (SDM) when an instance of the DE is created.
/// </summary>
sealed class EngineCreateEvent : AsynchronousEvent<idebugenginecreateevent2>, IDebugEngineCreateEvent2
{
private IDebugEngine2 engine;
public EngineCreateEvent(IDebugEngine2 engine)
{
this.engine = engine;
}
#region IDebugEngineCreateEvent2 Members
public int GetEngine(out IDebugEngine2 pEngine)
{
= engine;
pEngine return VSConstants.S_OK;
}
#endregion
}
/// <summary>
/// This interface is sent by the debug engine (DE) to the session debug manager (SDM) when a program is attached to.
/// </summary>
sealed class ProgramCreateEvent : AsynchronousEvent<idebugprogramcreateevent2>, IDebugProgramCreateEvent2
{
}
/// <summary>
/// This interface is sent by the debug engine (DE) to the session debug manager (SDM) when a module is loaded or unloaded.
/// </summary>
sealed class ThreadCreateEvent : AsynchronousEvent<idebugthreadcreateevent2>, IDebugThreadCreateEvent2
{
}
/// <summary>
/// This interface is sent by the debug engine (DE) to the session debug manager (SDM) when a program is loaded, but before any code is executed.
/// </summary>
sealed class LoadCompleteEvent : StoppingEvent<idebugloadcompleteevent2>, IDebugLoadCompleteEvent2
{
}
/// <summary>
/// This interface is sent by the debug engine (DE) to the session debug manager (SDM) when a thread has exited.
/// </summary>
sealed class ThreadDestroyEvent : StoppingEvent<idebugthreaddestroyevent2>, IDebugThreadDestroyEvent2
{
private uint exitCode;
public ThreadDestroyEvent(uint exitCode)
{
this.exitCode = exitCode;
}
#region IDebugThreadDestroyEvent2 Members
public int GetExitCode(out uint pdwExit)
{
= exitCode;
pdwExit return VSConstants.S_OK;
}
#endregion
}
/// <summary>
/// This interface is sent by the debug engine (DE) to the session debug manager (SDM) when a program has run to completion
/// or is otherwise destroyed.
/// </summary>
sealed class ProgramDestroyEvent : StoppingEvent<idebugprogramdestroyevent2>, IDebugProgramDestroyEvent2
{
private uint exitCode;
public ProgramDestroyEvent(uint exitCode)
{
this.exitCode = exitCode;
}
#region IDebugProgramDestroyEvent2 Members
public int GetExitCode(out uint pdwExit)
{
= exitCode;
pdwExit return VSConstants.S_OK;
}
#endregion
}
#endregion
/// <summary>
/// Extensions for IDebugEventCallback2 implementations
/// </summary>
static class IDebugEventCallback2Extension
{
static internal int Event(this IDebugEventCallback2 pCallback, IDebugEngine2 pEngine, IDebugProgram2 pProgram, IDebugThread2 pThread, IEvent pEvent)
{
= pEvent.IID;
Guid iid return pCallback.Event(pEngine, null, pProgram, pThread, pEvent, ref iid, pEvent.Attributes);
}
}
}