我希望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中“当抛出异常时”组框的哪里找到这个选项对话框,其中有“进入调试器”的选项吗?

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


当前回答

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

步骤1 步骤2

其他回答

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.

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

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

步骤1 步骤2

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

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

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

微软的文档说:

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

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