如何从包中设置"中断所有异常"

And*_*kin 19 .net visual-studio-2010 visual-studio visual-studio-debugging visual-studio-extensions

我想做一个扩展,以快速切换调试器中的CLR异常.
我尝试了几种方法,但都不令人满意.

这是我已经尝试过的:

  1. ExceptionSettings.SetBreakWhenThrown(MSDN)
    这非常慢(请参阅此Connect问题).我已经尝试了在抛出异常时问题" Toggle"Break的方法."使用宏或键盘快捷方式 "并且似乎都不可靠地工作:在大多数情况下只有顶级复选框被设置,并且在调试时它实际上不会中断异常.

  2. 调用DTE.ExecuteCommand("Debug.Exceptions")显示窗口,然后在它之前调用SetWindowsHookEx(MSDN)在它出现之前拦截它(这样用户就没有闪光).这似乎是可能的,因为我能够拦截消息并得到HWND.但它似乎很hacky并且窗口不是那么容易操作(它有一些奇怪的组合SysListView32与自定义复选框和SysTreeView32).所以我将它作为最后的机会解决方案.

  3. 以某种方式获取IDebugEngine2(MSDN)托管代码并在调试会话开始时调用IDebugEngine2.SetException(MSDN).这似乎是可能的,但我在获取调试引擎时遇到问题.我尝试过在MSDN论坛IVsLoader描述的方法,但我很确定它给了我一个与调试会话无关的新实例.

    我在这里也问过这个问题:" Visual Studio:如何从VS包中获取IDebugEngine2(除了IVsLoader) ",但没有得到解决方案.

    我已经尝试使用IVsDebugger.AdviseDebugEventCallback(MSDN),并通过实施的IDebugEventCallback2(MSDN),但我总是得到nullpEngine(没有IDebugEngineCreateEvent2任何).

    我得到IDebugSessionCreateEvent2(没有文档?)并且可以从中得到IDebugSession2它,但是它的SetException调用总是给我一个HRESULT错误的参数,所以我可能会在这里遗漏一些东西(调用SetException引擎从IVsLoader给出好的,只是不起作用).

是否有其他方法比那些方法更好或者我错过了现有的方法?


更新/注意:
如果你发现这个问题,因为你想要一个更快的"打破所有异常",我已经做了一个免费扩展,你可以从Visual Studio Gallery:Exception Breaker.

Sam*_*ell 10

自动化界面是不可能的.为了尝试使用它们来提高性能,我创建了从异常组到ExceptionSettings对象的缓存以及对象的异常名称ExceptionSetting.这允许我绕过ExceptionSettings.Item快速查找单个调用异常SetBreakWhenThrown,但不幸的是,内部实现SetBreakWhenThrown包括调用参数的调用,这反过来触发了一个困扰整个方法的内部枚举过程.缓存比不使用宏的代码快4倍,但我们仍然在讨论将IDE挂起几分钟的代码......

注意:以下说明仅针对Visual Studio 2012进行了测试.

步进通过SetBreakWhenThrown在汇编视图显示,该临界内部呼叫(验证后)sdm::CDebugManager::SetException.事实证明,shell调试器(SVsShellDebugger您投射到的服务IVsDebugger)实现了IDebuggerInternal它提供对当前的访问IDebugSession3.在我打开解决方案之后但在开始调试之前,此属性为非null.

IDebuggerInternal debugger = Package.GetGlobalService(typeof(SVsShellDebugger)) as IDebuggerInternal;
IDebugSession3 session = debugger != null ? debugger.CurrentSession : null;
Run Code Online (Sandbox Code Playgroud)

注意:IDebuggerInternal接口定义如下:

Microsoft.VisualStudio.Debugger.Interop.Internal, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Run Code Online (Sandbox Code Playgroud)

使用返回的信息EnumSetExceptions,我创建了一个成功改变CLR异常设置的结构!打电话IDebugSession3.SetException使调试器停止时,抛出异常.

EXCEPTION_INFO[] exceptionInfo =
{
    new EXCEPTION_INFO()
    {
        bstrExceptionName = typeof(NullReferenceException).FullName,
        bstrProgramName = null,
        dwCode = 0,
        pProgram = null,
        guidType = VSConstants.DebugEnginesGuids.ManagedOnly_guid,
        dwState = enum_EXCEPTION_STATE.EXCEPTION_STOP_FIRST_CHANCE
            | enum_EXCEPTION_STATE.EXCEPTION_STOP_SECOND_CHANCE
            | enum_EXCEPTION_STATE.EXCEPTION_JUST_MY_CODE_SUPPORTED
            | enum_EXCEPTION_STATE.EXCEPTION_STOP_USER_FIRST_CHANCE
            | enum_EXCEPTION_STATE.EXCEPTION_STOP_USER_UNCAUGHT
    }
};
hr = session.SetException(exceptionInfo);
Run Code Online (Sandbox Code Playgroud)

禁用调试器暂停,请IDebugSession3.RemoveSetException改用.