如何從包中設置“中斷所有異常”
我想進行擴展以在調試器中快速切換 CLR 異常的中斷。
我已經嘗試了幾種方法,但都不是令人滿意的。
這是我已經嘗試過的:
ExceptionSettings.SetBreakWhenThrown(MSDN)這非常慢(請參閱此連接問題)。我已經嘗試了來自問題“ Toggle “Break when an exception is throwed.”中的方法。使用宏或鍵盤快捷鍵“並且似乎都不能可靠地工作:在大多數情況下,只有頂級複選框被設置,並且在調試時它實際上不會因異常而中斷。 2. 呼叫
DTE.ExecuteCommand("Debug.Exceptions")以顯示視窗,並在此之前呼叫SetWindowsHookEx( MSDN ) 以在它出現之前攔截它(這樣使用者就不會閃現)。這似乎是可能的,因為我能夠攔截消息並獲取HWND. 但它似乎很hacky,並且視窗並不容易正確操作(它SysListView32與自定義復選框和有一些奇怪的組合SysTreeView32)。所以我把它作為最後的機會解決方案。 3. 在調試會話開始時以某種方式獲取IDebugEngine2( MSDN ) 託管程式碼和呼叫IDebugEngine2.SetException( MSDN )。這似乎是可能的,但我在獲取調試引擎時遇到了問題。我已經嘗試過在 MSDN 論壇上IVsLoader描述的方法,但我很確定它給了我一個與調試會話無關的新實例。我也在這裡問過這個問題:“ Visual Studio: How to get IDebugEngine2 from VS Package (except IVsLoader) ”,但沒有得到解決方案。
我嘗試過使用
IVsDebugger.AdviseDebugEventCallback(MSDN)並傳入IDebugEventCallback2(MSDN)的實現,但我總是得到null(pEngine也沒有IDebugEngineCreateEvent2)。我確實得到了
IDebugSessionCreateEvent2(無證?)並且可以從中得到IDebugSession2,但它的SetException呼叫總是給我一個HRESULT錯誤的論點,所以我可能在這裡遺漏了一些東西(SetException從引擎呼叫IVsLoader給了 OK,只是不起作用)。是否有其他方法比這些方法更好,或者我錯過了現有方法中的某些內容?
更新/注意:
如果您發現這個問題是因為您想要更快的“打破所有異常”,我已經做了一個免費的擴展,您可以從 Visual Studio Gallery 獲得:Exception Breaker。
自動化介面是不可能的。為了提高使用它們的性能,我創建了一個從異常組到對
ExceptionSettings像以及異常名稱到對象的記憶體ExceptionSetting。這使我能夠繞過ExceptionSettings.Item對呼叫的單個異常的快速查找SetBreakWhenThrown,但不幸的是,內部實現SetBreakWhenThrown包括驗證參數的呼叫,這反過來又觸發了困擾整個方法的內部列舉過程。記憶體比不使用宏的程式碼快大約 4 倍,但我們仍在討論會使 IDE 掛起幾分鐘的程式碼……注意:到目前為止,以下說明僅在 Visual Studio 2012 中進行了測試。
在反彙編
SetBreakWhenThrown視圖中逐步顯示,關鍵的內部呼叫(驗證後)是sdm::CDebugManager::SetException. 事實證明,shell 調試器(SVsShellDebugger您轉換到的服務IVsDebugger)實現IDebuggerInternal了提供對目前的訪問IDebugSession3。在我打開解決方案後但在我開始調試之前,此屬性非空。IDebuggerInternal debugger = Package.GetGlobalService(typeof(SVsShellDebugger)) as IDebuggerInternal; IDebugSession3 session = debugger != null ? debugger.CurrentSession : null;注意:
IDebuggerInternal介面定義在:Microsoft.VisualStudio.Debugger.Interop.Internal, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a使用返回的資訊
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);要禁用調試器暫停,請
IDebugSession3.RemoveSetException改用。