Toggle "Break when an exception is thrown." using macro or keyboard shortcut
Asked Answered
J

10

45

Edit: Visual Studio 2015's new exception window is so much faster than the old dialog that I no longer care as much about using a keyboard shortcut for it.

Is there a macro or keyboard shortcut that will toggle "break when an exception is thrown" without using the GUI?

Opening the dialog with ctrl+alt+e and checking the "Common Language Runtime Exceptions" "Thrown" box then clicking OK is simple enough, but this is something I do a lot. I would rather have a keyboard shortcut for this.

This question is a duplicate of Any have a Visual Studio shortcut/macro for toggling break on handled/unhandled exceptions?

However, the poster accepted an answer that doesn't really work, and I would really like an answer that does work.

The answer in the duplicate question is not acceptable because it toggles only one specific exception, not the entire CLR group.

"Well write a loop then." you say. But not so fast! Someone tried that already and it was uselessly slow. (Yes I've verified that its slow on my system as well.)

So the challenge is to use a macro to toggle the entire CLR Exceptions category in less than 1 or 2 seconds. This question is a duplicate of Any have a Visual Studio shortcut/macro for toggling break on handled/unhandled exceptions?

Jerky answered 5/6, 2009 at 20:37 Comment(4)
What version Visual Studio are you using?Dunaj
I'm using Visual Studio 2008, but a non-version specific solution is preferable, if possible.Jerky
@Jerky despite the fact that the accepted answer was written in 2009, there is a far better solution (down here) as a VS plugin that allows you to easily toggle CLR exceptions off/on with one keyboard shortcut. Please considering changing the accepted answer...Consolatory
@OferZelig Thanks for reminding me about this!Jerky
S
14

I have created a free Visual Studio extension that can do that reliably: Exception Breaker.
It uses undocumented IDebugSession2.SetException call that is very fast: all exceptions are set/unset in 20 to 60 milliseconds.

Sestertium answered 1/4, 2013 at 0:39 Comment(1)
Much <3. Will test it out soon.Jerky
R
18

Very similar to the other answer, but there is a special ExceptionSetting for the group.

Dim dbg As EnvDTE90.Debugger3 = DTE.Debugger
Dim exSettings As EnvDTE90.ExceptionSettings = dbg.ExceptionGroups.Item("Common Language Runtime Exceptions")
Dim exSetting As EnvDTE90.ExceptionSetting
Try
    exSetting = exSettings.Item("Common Language Runtime Exceptions")
Catch ex As COMException
    If ex.ErrorCode = -2147352565 Then
        exSetting = exSettings.NewException("Common Language Runtime Exceptions", 0)
    End If
End Try

If exSetting.BreakWhenThrown Then
    exSettings.SetBreakWhenThrown(False, exSetting)
Else
    exSettings.SetBreakWhenThrown(True, exSetting)
End If
Raid answered 11/6, 2009 at 14:58 Comment(7)
This gives an "invalid index" error for me with VS 2008. Any ideas?Jerky
Odd. It was working for me perfectly, but now I get the same error you do. Let me do some more digging.Raid
I've updated my code. It should work now. The change was to add the ExceptionSetting if it didn't exist.Raid
Hmm, ok this doesn't toggle the subsections for exceptions though. I just noticed this. :(Jerky
I tried this code, and while it successfully checks the top-level checkbox in the Exceptions dialog, that's the only checkbox that is checked. The checkboxes for individual exceptions remain unchecked, and so the debugger doesn't break when an exception is thrown.Reef
Voted down for same reason given by dss539 and othersApprobation
If I remember correctly, you need to do the operation from the dialog at least once before using the macro for the macro to work. And again IIRC this is per solution so if you remove the .suo or load another solution, you need to set it manually another time.Forayer
S
14

I have created a free Visual Studio extension that can do that reliably: Exception Breaker.
It uses undocumented IDebugSession2.SetException call that is very fast: all exceptions are set/unset in 20 to 60 milliseconds.

Sestertium answered 1/4, 2013 at 0:39 Comment(1)
Much <3. Will test it out soon.Jerky
A
4

Here's Bryce Kahle's very useful macro blindly updated to run in VS2010:

Sub ToggleExceptions()
    Dim dbg As EnvDTE100.Debugger5 = DTE.Debugger
    Dim exSettings As ExceptionSettings = dbg.ExceptionGroups.Item("Common Language Runtime Exceptions")
    Dim exSetting As ExceptionSetting
    Try
        exSetting = exSettings.Item("Common Language Runtime Exceptions")
    Catch ex As COMException
        If ex.ErrorCode = -2147352565 Then
            exSetting = exSettings.NewException("Common Language Runtime Exceptions", 0)
        End If
    End Try

    If exSetting.BreakWhenThrown Then
        exSettings.SetBreakWhenThrown(False, exSetting)
    Else
        exSettings.SetBreakWhenThrown(True, exSetting)
    End If

End Sub
Anthotaxy answered 19/4, 2010 at 20:26 Comment(2)
I've built an improvement on top of @PeterMacMurchy's answer. I added a command to the Menu Bar and assigned it to the macro above. I then added code in the macro that also changes the Caption of the command to reflect whether the setting is on or not. See my answer.Jo
Cool thanks! While it is true that this is the only check box that gets checked, it does actually break on the exceptions in the sub tree (regardless of their check state - Verified in 2010). Cheers!Fulton
D
2

Well, I wrote a VS2008 C# based plug-in that toggles the 386 exceptions, and it takes about 1 second per state toggle. I'm assuming that's due to COM inter-op.

This was based on the VB/macro code in the one of your links. I could not find an easier C++ method (but not ruling it out).

The next level would be to make a plug-in that has a keyboard binding, that then opens the Exceptions UI and then "clicks" the correct tick box for you.

Good luck.

Dunaj answered 11/6, 2009 at 9:38 Comment(3)
Thanks for trying. I suspect the issue is that toggling 1 setting or toggling 386 settings takes about the same amount of time IF toggling them as a batch. But I have only found a way to toggle them 1 at a time, so it takes 386 times longer than it should.Jerky
+1 thanks for contributing to this (I didn't want to +1 before because I didn't want this to get auto-accepted as an answer.)Jerky
Do you have a link to the plugin you created, would be very interested to use something like this in my own setupHepsibah
K
2

You could use a tool like AutoHotKey to create a recorded script (mouse clicks or key presses) and then assign it a hotkey that will play it back when pressed...

Kriskrischer answered 17/6, 2009 at 5:14 Comment(1)
Well part of the reason for wanting this is that the Exceptions dialog requires a non-trivial amount of time to open. My main goal is speed. Reducing repetition is an extra benefit, but not why I'm interested in this. So, good idea, but AHK doesn't quite suit my goals.Jerky
C
2

Just offering some info I found on this (here) as I was scouring the net in my futile attempt to help...

Someone else posed this same question and it was responded to by Gary Chang from MS Support, here's the quoted response:

I am afraid the Macro code cannot manipulate the operations on the Exceptions dialog box...

It's important to note that this posting is from December of 2005 so this response may no longer be accurate; either way, thought I'd throw it out there.

Cotidal answered 17/6, 2009 at 12:29 Comment(1)
Thanks for adding the info. BTW, is it Michael or Gary? On the site you linked, his name is listed as Gary Chang.Jerky
D
2

First i initalized a timer an then i call the command Exception.Debug. The timer hit, when the modal dialog is openend. If you use Win 7 with deactivated UAC SendKeys with ALT-Key will fail...i don't know why.

i played a little bit...try this (VS2010 EN):

Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports EnvDTE90a
Imports EnvDTE100
Imports System.Diagnostics
Imports System.Runtime.InteropServices

'...

Private WithEvents t As Timers.Timer
Private Sub t_Elapsed(ByVal ee As Object, ByVal dd As Timers.ElapsedEventArgs) Handles t.Elapsed
    t.Stop()
    ' Tastatureingaben simulieren
    System.Windows.Forms.SendKeys.SendWait("{DOWN}")
    System.Threading.Thread.Sleep(1500) ' Pause wichtig zum Laden des Exceptionbaums
    System.Windows.Forms.SendKeys.SendWait("%t")
    System.Windows.Forms.SendKeys.SendWait("{ENTER}")
End Sub
Public Sub toggleCLRExceptions()
    If DTE.Solution.Count <= 0 Then
        MsgBox("Nicht ohne geöffnete Solution!")
        Exit Sub
    End If
    ' Timer wird benötigt, da der Dialog Modal ist
    ' und weitere Befehle im Macro werden erst nach beenden des Dialogs ausgeführt
    t = New Timers.Timer()
    t.Interval = 0.5
    t.Start()
    DTE.ExecuteCommand("Debug.Exceptions")
    'System.Windows.Forms.SendKeys.SendWait("^%e") ' alternativ: STRG+ALT+e
    System.Threading.Thread.Sleep(200)
    If isCLRExceptionsActive() Then
        MsgBox("BREAK @CLR-Exception", MsgBoxStyle.Information, "Info")
    Else
        MsgBox("NO BREAK @CLR-Exception", MsgBoxStyle.Information, "Info")
    End If
End Sub

Function isCLRExceptionsActive() As Boolean
    ' prüft, ob Setting Debug CLR-Exceptions aktiviert/deaktivert ist
    Dim dbg As EnvDTE100.Debugger5 = DTE.Debugger
    Dim exSettings As ExceptionSettings = dbg.ExceptionGroups.Item("Common Language Runtime Exceptions")
    Dim exSetting As ExceptionSetting
    Try
        exSetting = exSettings.Item("Common Language Runtime Exceptions")
    Catch ex As COMException
        If ex.ErrorCode = -2147352565 Then
            exSetting = exSettings.NewException("Common Language Runtime Exceptions", 0)
        End If
    End Try
    Return exSetting.BreakWhenThrown
End Function

'...
Defame answered 26/10, 2011 at 13:12 Comment(0)
D
1

The suggestion of setting the special ExceptionSetting for the group does indeed toggle the state of the top-level checkbox. However, it doesn't seem to toggle the individual Exceptions below it in the tree, and moreover, my process does not stop when such exceptions are thrown as it does if I manually check the top-level checkbox. Do you see different behavior?

Dialysis answered 16/10, 2009 at 19:59 Comment(1)
Ethan, yes I also noted this. See my comment on the "accepted answer". My comment is hidden by default. You have to "view all comments".Jerky
A
1

My macro to ignore current CLR exception in runtime. It works like a button 'disable catching this exception type' when an exception pops at debug-time.

Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports EnvDTE90a
Imports EnvDTE100
Imports System.Diagnostics
Imports Microsoft.VisualBasic
Imports Microsoft.VisualBasic.ControlChars

' execute Macros.MyMacros.VSDebuggerExceptions.IgnoreCurrentExceptionWhenThrown from VS Command Window

Public Module VSDebuggerExceptions

    Sub BreakWhenThrown(Optional ByVal strException As String = "")
        Dim dbg As Debugger3 = DTE.Debugger
        Dim eg As ExceptionSettings = _
            dbg.ExceptionGroups.Item("Common Language Runtime Exceptions")
        eg.SetBreakWhenThrown(True, eg.Item(strException))
    End Sub

    ' copied from Utilities module (samples)
    Function GetOutputWindowPane(ByVal Name As String, Optional ByVal show As Boolean = True) As OutputWindowPane
        Dim window As Window
        Dim outputWindow As OutputWindow
        Dim outputWindowPane As OutputWindowPane

        window = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindOutput)
        If show Then window.Visible = True
        outputWindow = window.Object
        Try
            outputWindowPane = outputWindow.OutputWindowPanes.Item(Name)
        Catch e As System.Exception
            outputWindowPane = outputWindow.OutputWindowPanes.Add(Name)
        End Try
        outputWindowPane.Activate()
        Return outputWindowPane
    End Function

    Private WithEvents t As Timers.Timer

    ' Adds the current exception to ignore list
    Sub IgnoreCurrentExceptionWhenThrown()
        Dim commandWin As EnvDTE.CommandWindow
        commandWin = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindCommandWindow).Object

        Select Case DTE.Debugger.CurrentMode
            Case dbgDebugMode.dbgDesignMode
                commandWin.OutputString("This macro is not enabled in Design Mode. Run it in Break Mode." + vbCrLf)
                Return

            Case dbgDebugMode.dbgRunMode
                commandWin.OutputString("This macro is not enabled in Run Mode. Run it in Break Mode." + vbCrLf)
                Return
        End Select

        commandWin.OutputString(Environment.NewLine)
        commandWin.OutputString("Trying to get the information about current exception.." + Environment.NewLine)

        Dim dbg As Debugger3 = DTE.Debugger
        Dim currentExpression As Expression = dbg.GetExpression("$exception", False)
        Try    
            Dim currentExceptionTypeString As String = currentExpression.DataMembers.Item(1).Type
            commandWin.OutputString("Detected current exception type is : " + currentExceptionTypeString + Environment.NewLine)

            Dim flag As Boolean = True
            Dim eg As ExceptionSettings = dbg.ExceptionGroups.Item("Common Language Runtime Exceptions")
            Try
                eg.SetBreakWhenThrown(False, eg.Item(currentExceptionTypeString))
            Catch exc As Exception
                commandWin.OutputString("Cannot find this exception, trying to create.." + currentExceptionTypeString + Environment.NewLine)
                '
                eg.NewException(currentExceptionTypeString, New Random().Next)
                eg.SetBreakWhenThrown(False, eg.Item(currentExceptionTypeString))
                eg.SetBreakWhenUserUnhandled(True, eg.Item(currentExceptionTypeString))
                flag = False
            End Try

            commandWin.OutputString(Environment.NewLine)
            commandWin.OutputString("Exception '" + currentExceptionTypeString + "' added to ignore list.")
            commandWin.OutputString(Environment.NewLine)

            t = New Timers.Timer()
            ' small interval to send keys after DTE will start to exec command
            t.Interval = 0.1
            t.Start()
            DTE.ExecuteCommand("Debug.Exceptions")

        Catch exc As Exception
            commandWin.OutputString("Error occured")
        End Try
    End Sub

    Private Sub t_Elapsed(ByVal ee As Object, ByVal dd As Timers.ElapsedEventArgs) Handles t.Elapsed
        t.Stop()
        ' only press Ok to apply changed exceptions settings to debugger
        System.Windows.Forms.SendKeys.SendWait("%t")
        System.Windows.Forms.SendKeys.SendWait("{ENTER}")
    End Sub

End Module
Atalya answered 25/1, 2012 at 11:18 Comment(1)
Thanks for the contribution, I'll try it out when I get a chance.Jerky
A
1

CTRL + ALT + E ALT + T Enter

works for me

Australorp answered 12/8, 2013 at 15:50 Comment(1)
That does work, but launching the Exceptions dialog is excruciatingly slow. So it's more like CTRL + ALT + E [drink half your coffee] ALT + T Enter.Jerky

© 2022 - 2024 — McMap. All rights reserved.