220

I would like Visual Studio to break when a handled exception happens (i.e. I don't just want to see a "First chance" message, I want to debug the actual exception).

e.g. I want the debugger to break at the exception:

try
{
   System.IO.File.Delete(someFilename);
}
catch (Exception)
{
   //we really don't care at runtime if the file couldn't be deleted
}

I came across these notes for Visual Studio.NET:

1) In VS.NET go to the Debug Menu >> "Exceptions..." >> "Common Language Runtime Exceptions" >> "System" and select "System.NullReferenceException"

2) In the bottom of that dialog there is a "When the exception is thrown:" group box, select "Break into the debugger"

3) Run your scenario. When the exception is thrown, the debugger will stop and notify you with a dialog that says something like: "An exception of type "System.NullReferenceException" has been thrown. [Break] [Continue]"

Hit [Break]. This will put you on the line of code that's causing the problem.

But they do not apply to Visual Studio 2005 (there is no Exceptions option on the Debug menu).

Does anyone know where the find this options dialog in Visual Studio that the "When the exception is thrown" group box, with the option to "Break into the debugger"?

Update: The problem was that my Debug menu didn't have an Exceptions item. I customized the menu to manually add it.

James Dunn
  • 8,064
  • 13
  • 53
  • 87
Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
  • 23
    In VS2015 it was under Debug->Windows->Exception Settings – PeterVermont Nov 11 '16 at 14:54
  • 2
    Took me a while to find how to **restore** the **default** exception settings after i changed some of exception setting, therefore a new answer. [restore exception settings to default](https://i.stack.imgur.com/Tkajf.jpg) – Mabito Apr 02 '20 at 05:26

8 Answers8

211

With a solution open, go to the Debug - Windows - Exception Settings (Ctrl+Alt+E) menu option. From there you can choose to break on Thrown or User-unhandled exceptions.

EDIT: My instance is set up with the C# "profile" perhaps it isn't there for other profiles?

Dmitry Fedorkov
  • 4,301
  • 1
  • 21
  • 30
Austin Salonen
  • 49,173
  • 15
  • 109
  • 139
  • 13
    i just don't have such an option. That would explain my confusion. – Ian Boyd Sep 22 '08 at 19:26
  • 1
    Are you missing the Debug menu altogether? – Austin Salonen Sep 22 '08 at 19:29
  • 68
    i had the debug menu, but no Exceptions options. i customized the menu to manually add it; the shortcut key worked either way (Ctrl+Alt+E) – Ian Boyd Sep 22 '08 at 19:40
  • 3
    Also, you can reset the VS2010 environement, by going to "Tools", "Import Export Settings" and select a reset to the C# environment... it contains the Exceptions Submenu item – BeardinaSuit Feb 14 '12 at 16:28
  • 1
    For enabling the *Exception* menu item, see *[How to: Break When an Exception is Thrown](http://msdn.microsoft.com/en-us/library/d14azbfh.aspx)* (MSDN), section *"To add the Exceptions command to the Debug menu"* (this could be incorporated into the answer). – Peter Mortensen Feb 10 '14 at 15:09
  • 1
    @AustinSalonen Isn't the OP asking how to break on *handled* exceptions? – Matthew Jul 04 '15 at 22:31
  • 2
    @Matt, that's what _Break on Thrown_ does. – Austin Salonen Jul 06 '15 at 16:21
  • 30
    I selected `Common Language Runtime Exceptions` > `` under Visual Studio 2017 and all of my wildest dreams came true. – Aaron Newton Oct 16 '17 at 04:56
  • 14
    Visual Studio 2015: Debug -> Windows -> Exception Settings – achecopar Nov 07 '17 at 15:05
  • @AaronNewton Maybe make an answer out of your comment. There are answers which suggest checking the "All Exceptions not in this list" but they are not specifically pointing to `Common Language Runtime Exceptions` > `` – daniatic Aug 15 '18 at 12:38
  • What about custom, user-defined exceptions that are not CLR exceptions? – thatWiseGuy Jan 16 '19 at 19:13
  • @thatWiseGuy I was able to add an exception that came from an extension dll with the green plus in that menu (ctrl+alt+e) and paste the fully-qualified class name. VS 2019 pro. Should theoretically work the same for extensions originating in the solution. – memtha Aug 10 '21 at 19:09
  • In my case, I could not find any debug option that would invoke the debugger in a handled exception. In the end, it was easier for me to just (temporarily) invoke "throw;" in the exception handler. – KWallace Jan 22 '22 at 17:32
63

There is an 'exceptions' window in VS2005 ... try Ctrl+Alt+E when debugging and click on the 'Thrown' checkbox for the exception you want to stop on.

Valery Viktorovsky
  • 6,487
  • 3
  • 39
  • 47
Rob Walker
  • 46,588
  • 15
  • 99
  • 136
  • That's exactly what i want. Where is that in the menu? For the life of me i cannot find it. – Ian Boyd Sep 22 '08 at 19:24
  • The keyboard shortcut can change according to profile (C# developer, C++ developer, etc.) – Asaf R Sep 22 '08 at 19:29
  • 1
    I have a menu item: Debug -> Exceptions. This is with VS2005 Professional. Are you running an Express edition? – Rob Walker Sep 22 '08 at 19:34
  • 5
    if you want the Exceptions menu item: Select Tools | Customize.... Click on the Commands tab. Select the Debug category in the Categories box. Find the Exceptions... command item, then drag it to the Debug menu at the top of the application, dropping it in the appropriate place in the menu. (found in the comments on: http://blogs.vertigo.com/personal/keithc/Blog/archive/2007/07/20/missing-menu-options-in-visual-studio-2005.aspx ) – sotto Jun 10 '10 at 09:35
59

Took me a while to find the new place for expection settings, therefore a new answer.

Since Visual Studio 2015 you control which Exceptions to stop on in the Exception Settings Window (Debug->Windows->Exception Settings). The shortcut is still Ctrl-Alt-E.

The simplest way to handle custom exceptions is selecting "all exceptions not in this list".

Here is a screenshot from the english version:

enter image description here

Here is a screenshot from the german version:

enter image description here

Beginner
  • 5,277
  • 6
  • 34
  • 71
29

From Visual Studio 2015 and onward, you need to go to the "Exception Settings" dialog (Ctrl+Alt+E) and check off the "Common Language Runtime Exceptions" (or a specific one you want i.e. ArgumentNullException) to make it break on handled exceptions.

Step 1 Step 1 Step 2 Step 2

Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
Sameer Alibhai
  • 3,092
  • 4
  • 36
  • 36
10

Check Managing Exceptions with the Debugger page, it explains how to set this up.

Essentially, here are the steps (during debugging):

  1. On the Debug menu, click Exceptions.

  2. In the Exceptions dialog box, select Thrown for an entire category of exceptions, for example, Common Language Runtime Exceptions.

    -or-

    Expand the node for a category of exceptions, for example, Common Language Runtime Exceptions, and select Thrown for a specific exception within that category.

kenorb
  • 155,785
  • 88
  • 678
  • 743
Guy Starbuck
  • 21,603
  • 7
  • 53
  • 64
2

A technique I use is something like the following. Define a global variable that you can use for one or multiple try catch blocks depending on what you're trying to debug and use the following structure:

if(!GlobalTestingBool)
{
   try
   {
      SomeErrorProneMethod();
   }
   catch (...)
   {
      // ... Error handling ...
   }
}
else
{
   SomeErrorProneMethod();
}

I find this gives me a bit more flexibility in terms of testing because there are still some exceptions I don't want the IDE to break on.

Spencer Ruport
  • 34,865
  • 12
  • 85
  • 147
  • 3
    This is a useful technique -- it turns the handled exception into an unhandled exception, so the debugger stops on it automatically. I'm not sure why it was downvoted, unless it was that there's no good way to set your GlobalTestingBool. Another, possibly better option is to use Debugger.IsAttached. – Joe White Jul 18 '10 at 14:16
  • You'd have to add this around every try/catch and recompile your code. Not very useful if you're already in the middle of debugging something. – Max Nov 01 '17 at 14:15
  • 1
    An exception should be thrown in code if there is an exceptional condition - something unacceptable - and it should be caught at a level where a decision can be made as to how to handle it. Code such as this over complicates the paths of execution. – Lee Oades May 12 '18 at 21:15
  • i know this is really old answer, but for random googlers like me, you can just add `catch(){/*handle or not*/ throw; } // throw without any exception specified will rethrow original exception with original callstack etc` – Jan 'splite' K. Jan 03 '20 at 12:37
1

The online documentation seems a little unclear, so I just performed a little test. Choosing to break on Thrown from the Exceptions dialog box causes the program execution to break on any exception, handled or unhandled. If you want to break on handled exceptions only, it seems your only recourse is to go through your code and put breakpoints on all your handled exceptions. This seems a little excessive, so it might be better to add a debug statement whenever you handle an exception. Then when you see that output, you can set a breakpoint at that line in the code.

markysdad
  • 39
  • 6
0

There are some other aspects to this that need to be unpacked. Generally, an app should not throw exceptions unless something exceptional happens.

Microsoft's documentation says:

For conditions that are likely to occur but might trigger an exception, consider handling them in a way that will avoid the exception.

and

A class can provide methods or properties that enable you to avoid making a call that would trigger an exception.

Exceptions degrade performance and disrupt the debugging experience because you should be able to break on all exceptions in any running code.

If you find that your debugging experience is poor because the debugger constantly breaks on pointless exceptions, you may need to detect handled exceptions in your tests. This technique allows you to fail tests when code throws unexpected exceptions.

Here are some helper functions for doing that

public class HandledExceptionGuard
{
    public static void DoesntThrowException(Action test,
      Func<object?, Exception, bool>? ignoreException = null)
    {
        var errors = new List<ExceptionInformation>();

        EventHandler<FirstChanceExceptionEventArgs> handler = (s, e) =>
        {
            if (e.Exception is AssertFailedException) return;
            if (ignoreException?.Invoke(s, e.Exception) ?? false) return;
            errors.Add(new ExceptionInformation(s, e.Exception, AppDomain.CurrentDomain.FriendlyName));
        };

        AppDomain.CurrentDomain.FirstChanceException += handler;

        test();

        AppDomain.CurrentDomain.FirstChanceException -= handler;

        if (errors.Count > 0)
        {
            throw new ExceptionAssertionException(errors);
        }
    }

    public async static Task DoesntThrowExceptionAsync(Func<Task> test,
      Func<object?, Exception, bool>? ignoreException = null)
    {
        var errors = new List<ExceptionInformation>();

        EventHandler<FirstChanceExceptionEventArgs> handler = (s, e) =>
        {
            if (e.Exception is AssertFailedException) return;
            if (ignoreException?.Invoke(s, e.Exception) ?? false) return;
            errors.Add(new ExceptionInformation(s, e.Exception, AppDomain.CurrentDomain.FriendlyName));
        };

        AppDomain.CurrentDomain.FirstChanceException += handler;

        await test();

        AppDomain.CurrentDomain.FirstChanceException -= handler;

        if (errors.Count > 0)
        {
            throw new ExceptionAssertionException(errors);
        }
    }
}

If you wrap any code in these methods as below, the test will fail when a handled exception occurs. You can ignore exceptions with the callback. This validates your code against unwanted handled exceptions.

[TestClass]
public class HandledExceptionTests
{
    private static void SyncMethod()
    {
        try
        {
            throw new Exception();
        }
        catch (Exception)
        {

        }
    }

    private static async Task AsyncMethod()
    {
        try
        {
            await Task.Run(() => throw new Exception());
        }
        catch (Exception)
        {

        }
    }

    [TestMethod]
    public void SynchronousTest()
    {
        HandledExceptionGuard.DoesntThrowException(() => SyncMethod());
    }

    [TestMethod]
    public async Task AsyncTest()
    {
        await HandledExceptionGuard.DoesntThrowExceptionAsync(() => AsyncMethod());
    }
}
Christian Findlay
  • 6,770
  • 5
  • 51
  • 103