我希望Visual Studio在处理异常发生时中断(即我不只是想看到“第一次机会”消息,我想调试实际的异常)。

例:我希望调试器在异常时中断:

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

我偶然发现了这些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.

但是它们不适用于Visual Studio 2005(在Debug菜单上没有例外选项)。

有人知道在Visual Studio中“当抛出异常时”组框的哪里找到这个选项对话框,其中有“进入调试器”的选项吗?

更新:问题是我的调试菜单没有异常项。我自定义菜单手动添加它。


VS2005中有一个“例外”窗口…调试时尝试按Ctrl+Alt+E,并单击要停止的异常的“抛出”复选框。


打开解决方案后,转到调试- Windows -异常设置(Ctrl+Alt+E)菜单选项。从那里你可以选择中断抛出的或用户未处理的异常。

编辑:我的实例是用c#“配置文件”设置的,也许它没有其他配置文件?


检查使用调试器管理异常页面,它解释了如何设置它。

本质上,以下是(在调试期间)的步骤:

在“调试”菜单上,单击“例外”。 在“异常”对话框中,为整个异常类别选择“抛出”,例如“公共语言运行时异常”。 或者, 展开异常类别(例如,公共语言运行时异常)的节点,并为该类别中的特定异常选择抛出。


我使用的一种技巧如下所示。定义一个全局变量,可以用于一个或多个try catch块,这取决于你要调试的内容,并使用以下结构:

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

我发现这在测试方面给了我更多的灵活性,因为仍然存在一些我不希望IDE中断的异常。


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.


我花了一段时间才找到期望设置的新地方,因此有了一个新的答案。

自Visual Studio 2015以来,您可以在异常设置窗口(调试->Windows->异常设置)中控制要停止的异常。快捷键仍然是Ctrl-Alt-E。

处理自定义异常的最简单方法是选择“不在此列表中的所有异常”。

以下是英文版的截图:

以下是德国版的截图:


从Visual Studio 2015及以后,你需要进入“异常设置”对话框(Ctrl+Alt+E)并选中“公共语言运行时异常”(或你想要的特定的一个,例如ArgumentNullException),使其在处理异常时中断。

步骤1 步骤2


还有一些其他方面需要解释。通常,除非发生异常,否则应用程序不应该抛出异常。

微软的文档说:

对于可能发生但可能触发异常的情况,请考虑以避免异常的方式处理它们。

and

类可以提供方法或属性,使您能够避免进行可能触发异常的调用。

异常会降低性能并破坏调试体验,因为您应该能够中断任何正在运行的代码中的所有异常。

如果您发现调试经验很差,因为调试器经常在毫无意义的异常上中断,那么您可能需要在测试中检测已处理的异常。这种技术允许您在代码抛出意外异常时失败测试。

这里有一些辅助函数

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);
        }
    }
}

如果在这些方法中包装如下所示的任何代码,当发生已处理的异常时,测试将失败。你可以忽略回调的异常。这将针对不想要的已处理异常验证您的代码。

[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());
    }
}