在Visual Studio扩展中,如何检测调试器继续运行?

9
我希望我的 Visual Studio 扩展程序能够对调试事件作出反应。我已经注册了一个 IDebugEventCallback2,并且收到了事件,但是对于每个事件,我只得到了一个不透明的 IDebugEvent2 和一个 GUID,其中许多不仅没有记录文档,而且在 Web 上(或我的注册表中)也找不到。
我目前的具体需求是要知道进程何时继续-即用户已按下“继续”、“运行到光标”等。我应该寻找哪个 GUID?
还是说我应该订阅其他事件家族?
(更一般地说,当许多事件在 MSDN 或其他任何地方都没有出现时,是否有我错过的某种方法可以了解传递到我的 IDebugEventCallback2::Event 回调的事件?谢谢!)
2个回答

6
这并不容易。像“继续”和“运行到光标处”这样的操作是Visual Studio实现的抽象,与调试引擎没有任何对应的唯一事件。调试引擎事件报告接口IDebugEventCallback2只会在诸如创建断点或到达断点等精细事件上通知您。
虽然Visual Studio使您能够以编程方式执行“继续”和“运行到光标处”等操作,但它没有直接的方法来在执行它们时得到通知。
您可以使用EnvDTE.DebuggerEvents.OnXxx事件来获取有关即将发生的情况的通知。特别是,OnEnterBreakMode事件使您能够拦截断点命中并可能采取某些操作。您还可以在事件处理程序中使用当前的EnvDTE.Debugger检查所有已达到的断点的详细信息。
现在,只要付出一些努力,您就可以使用这些结构来实现与所有Visual Studio调试操作相对应的事件,包括 继续运行到光标。如果您需要其他EnvDTE.DebuggerEvents未提供的事件(例如插入断点时),您只能使用IDebugEventCallback2.Event。在这种情况下,如果您有特定的事件,请明确说明它们,我可能能够告诉您相应的IDebugEventCallback2.Event GUID。

谢谢!看起来Continue的特定情况(或变体,如Run to Cursor - 我不需要区分)应该由DebuggerEvents.OnEnterRunMode处理 - 对吗?但是回到IDebugEventCallback2,调试Visual Studio后,我发现事件{29e2d4a0-503e-4e17-91ea-ea021570a857}似乎对应着同样的事情(我称之为“GUID_ExitBreakModeEvent”,基于我在Visual Studio堆栈中看到的内容)。我还使用{ce6f92d3-4222-4b1e-830d-3ecff112bf22}来检测调试器上下文何时更改 - 这合理吗?有更好的替代方案吗? - RichieHindle
事件{29e2d4a0-503e-4e17-91ea-ea021570a857}对应于内部接口Microsoft.VisualStudio.Debugger.Interop.Internal.IDebugExitBreakStateEvent,每当断点被退出时就会发生。这意味着它将在“继续”、“运行到光标”和所有类型的步骤上发生。 - Hadi Brais
我不确定你所说的“调试器上下文更改”是什么意思。 - Hadi Brais
DebuggerEvents.OnEnterRunMode 就像 IDebugExitBreakStateEvent 一样。 - Hadi Brais
非常感谢 - 这非常有帮助!我所说的“调试器上下文更改”,例如,是指通过在“调用堆栈”窗口中双击来切换到新的堆栈帧。当前语句的更改 - 黄色指针在边缘的位置。 - RichieHindle
显示剩余8条评论

2
您可能在这里走错了路,IDebugXxx接口实际上是为创建自己的调试引擎而设计的。尽管它们仍然有用,可以查看现有引擎中正在发生的事情,但您应该使用QueryInterface()来发现与事件匹配的特定接口,例如IDebugEngineCreateEvent2、IDebugProcessCreateEvent2、IDebugProcessDestroyEvent2等等。它们有很多,它们列在VSSDK\VisualStudioIntegration\Common\Inc\msdbg.h头文件中,并包括它们的IID。
最好的方法是查看this sample,它展示了如何将事件通知解析为特定的接口。AD7Events.cs源文件显示了包装器。请记住,此示例是为了展示如何创建引擎,而不是如何使用已经内置于VS中的引擎。
但是,确实无法从中获得“继续调试”事件。由于调试引擎已经负责通过调用IDebugProgram3::Continue()来处理它,因此它不需要该事件。
你要找的应该是IVsDebugger.AdviseDebuggerEvents()。那个会告诉你内置调试器正在做什么。你需要传递一个实现了IVsDebuggerEvents接口的类的对象,你的OnModeChanged()方法将被调用并带有一个DBGMODE通知。我没有看到很多很好的示例来演示使用,这个网页可能会有所帮助。

谢谢!OnModeChanged()函数可用。值得注意的是,它会有短暂延迟,并且不总是触发。如果您跨越一个运行时间较长的函数,您将会得到一个Run事件,然后是一个Break事件,但如果您跨越一个快速的函数,您只会得到一个Break事件。 - RichieHindle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接