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)
            {
                eventAttributes = Attributes;
                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)
            {
                pEngine = engine;
                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)
            {
                pdwExit = exitCode;
                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)
            {
                pdwExit = exitCode;
                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)
            {
                Guid iid = pEvent.IID;
                return pCallback.Event(pEngine, null, pProgram, pThread, pEvent, ref iid, pEvent.Attributes);
            }
        }
    }