envdte не запускает некоторые события отладки

Я пытаюсь использовать envdte для связи с отладчиком Visual Studio. К сожалению, я не могу запустить события OnEnterBreakMode/OnEnterRunMode/OnEnterDesignMode. Событие OnContextChanged работает хорошо, но остальные не запускаются.

Ниже приведен мой код для воспроизведения проблемы консольного приложения C# (я пытался максимально упростить его)

Наиболее важным является класс Debugger. Я тестирую его таким образом: 1. Скомпилируйте код ниже 2. Откройте проект C++ в Visual Studio 3. Запустите скомпилированную программу из шага 1 4. Подключитесь к Visual Studio (введите 0 и введите) 5. Запустите отладку этого проекта C++ - запустите отладку, добавить точки останова шаг, шаг, шаг, f5 ...

Наконец, единственный вывод, который я могу получить, выглядит следующим образом:

Select Debugger Number:
0 - !VisualStudio.DTE.15.0:13000
0
Context Changed
Context Changed
Context Changed
Context Changed
Context Changed
Context Changed
Context Changed
Context Changed
Context Changed
Context Changed
Context Changed

Мой тестовый код:

using System;
using System.Collections.Generic;
using EnvDTE;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;

namespace DebugWatchTest
{
    class DebuggerConnector
    {
        [DllImport("ole32.dll")]
        private static extern int CreateBindCtx(uint reserved, out IBindCtx ppbc);
        public static List<string> FindDebuggers()
        {
            List<string> result = new List<string>();

            IBindCtx bindCtx = null;
            IRunningObjectTable rot = null;
            IEnumMoniker enumMonikers = null;

            try
            {
                Marshal.ThrowExceptionForHR(CreateBindCtx(reserved: 0, ppbc: out bindCtx));
                bindCtx.GetRunningObjectTable(out rot);
                rot.EnumRunning(out enumMonikers);

                IMoniker[] moniker = new IMoniker[1];
                IntPtr numberFetched = IntPtr.Zero;
                while (enumMonikers.Next(1, moniker, numberFetched) == 0)
                {
                    string name = null;
                    IMoniker runningObjectMoniker = moniker[0];

                    if (runningObjectMoniker != null)
                    {
                        try {
                            runningObjectMoniker.GetDisplayName(bindCtx, null, out name);
                        }
                        catch (UnauthorizedAccessException)
                        { }  // Do nothing, there is something in the ROT that we do not have access to.
                    }

                    const string progName = "!VisualStudio.DTE";
                    if (!string.IsNullOrEmpty(name) && name.StartsWith(progName, StringComparison.Ordinal))
                    {
                        result.Add(name);
                    }
                }
            }
            finally
            {
                if (enumMonikers != null) {
                    Marshal.ReleaseComObject(enumMonikers);
                }

                if (rot != null) {
                    Marshal.ReleaseComObject(rot);
                }

                if (bindCtx != null) {
                    Marshal.ReleaseComObject(bindCtx);
                }
            }

            return result;
        }
        public static DTE Connect(string debuggerName)
        {
            object runningObject = null;
            IBindCtx bindCtx = null;
            IRunningObjectTable rot = null;
            IEnumMoniker enumMonikers = null;

            try
            {
                Marshal.ThrowExceptionForHR(CreateBindCtx(reserved: 0, ppbc: out bindCtx));
                bindCtx.GetRunningObjectTable(out rot);
                rot.EnumRunning(out enumMonikers);

                IMoniker[] moniker = new IMoniker[1];
                IntPtr numberFetched = IntPtr.Zero;
                while (enumMonikers.Next(1, moniker, numberFetched) == 0)
                {
                    string name = null;
                    IMoniker runningObjectMoniker = moniker[0];

                    if (runningObjectMoniker != null)
                    {
                        try {
                            runningObjectMoniker.GetDisplayName(bindCtx, null, out name);
                        }
                        catch (UnauthorizedAccessException)
                        { }  // Do nothing, there is something in the ROT that we do not have access to.
                    }

                    if (!string.IsNullOrEmpty(name) && name.Equals(debuggerName, StringComparison.Ordinal))
                    {
                        Marshal.ThrowExceptionForHR(rot.GetObject(runningObjectMoniker, out runningObject));
                        break;
                    }
                }
            }
            finally
            {
                if (enumMonikers != null) {
                    Marshal.ReleaseComObject(enumMonikers);
                }
                if (rot != null) {
                    Marshal.ReleaseComObject(rot);
                }
                if (bindCtx != null) {
                    Marshal.ReleaseComObject(bindCtx);
                }
            }

            if (runningObject is DTE)
            {
                return runningObject as DTE;
            }
            return null;
        }
    }

    class Debugger
    {
        DTE instance;
        Events e;
        DebuggerEvents de;
        public Debugger(DTE d)
        {
            instance = d;
            e = instance.Events;
            de = e.DebuggerEvents;

            de.OnContextChanged += De_OnContextChanged;
            de.OnEnterBreakMode += De_OnEnterBreakMode;
            de.OnEnterRunMode += De_OnModeChanged;
            de.OnEnterDesignMode += De_OnModeChanged;
        }

        private void De_OnModeChanged(dbgEventReason Reason) {
            Console.WriteLine("Mode Changed");
        }

        private void De_OnEnterBreakMode(dbgEventReason Reason, ref dbgExecutionAction ExecutionAction)
        {
            Console.WriteLine("BreakMode");
        }

        private void De_OnContextChanged(Process NewProcess, EnvDTE.Program NewProgram, Thread NewThread, StackFrame NewStackFrame)
        {
            Console.WriteLine("Context Changed");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            List<string> debuggers = DebuggerConnector.FindDebuggers();
            Console.WriteLine("Select Debugger Number:");
            for(int i = 0; i < debuggers.Count;++i)
                Console.WriteLine($"{i} - {debuggers[i]}");
            string number = Console.ReadLine();
            string processId = debuggers[int.Parse(number)];
            DTE msvc = DebuggerConnector.Connect(processId);
            Debugger d = new Debugger(msvc);
            while (true)
            { }
        }
    }
}

Aby намекает, что не так в моем коде?

0 ответов

Другие вопросы по тегам