有没有办法阻止Visual Studio打破特定方法中的异常?

时间:2011-03-01 09:37:54

标签: visual-studio visual-studio-2010 debugging exception visual-studio-debugging

我知道我可以控制Visual Studio根据类型处理异常的方式,以及最终使用“异常”对话框捕获异常的事实。

但是,当我调用特定方法时,我有一个内部抛出(和捕获)ArgumentOutOfRange异常的库。抛出异常(并被库捕获)可能有1%的时间,但我正在调用这个方法。编辑说这是设计的(事实上,他们选择的设计是有道理的)。

问题在于,每次抛出异常时我都不希望Visual Studio中断。

  • 我不想在ArgumentOutOfRange例外情况上停止,因为我的代码中可能有一些例子,并希望打破这些例外。
  • 我不想启用“只是我的代码”调试,因为我担心我的代码之外抛出的异常(特别是出于性能原因)

有没有办法实现这个目标?我一直在研究属性(例如DebuggerStepThrough),但还没找到足够的东西。

有关如何执行此操作的任何提示?

3 个答案:

答案 0 :(得分:2)

我认为在视觉工作室中这是不可能的,但肯定是在WinDbg中。 请参阅示例http://blogs.msdn.com/b/alejacma/archive/2009/08/24/managed-debugging-with-windbg-breaking-on-an-exception-part-1.aspx

从侧面说明,似乎从visual studio 2010开始,您可以加载并使用WinDbg扩展DLL直接提供附加功能(可能包括您需要的功能),但我还没有尝试过 - 请参阅示例{{ 3}}

答案 1 :(得分:2)

  

我不想启用“只是我的代码”调试

是的,现在就到此为止。那就是完全您需要的功能,以避免不必要的调试器中断。如果你不想知道别人的蹩脚代码,那么请重新打开该复选框。

当程序员使用异常进行流量控制时,这总是会失去作用。一种非常普遍的罪行。它需要两个将它们变成混乱,将调试会话变成一个非常乏味的点击噩梦。当您需要调试器功能打破第一次机会异常时,如果其他人也需要它,您基本上就会丢失。

每个人都希望他们可以神奇地使用[DebuggerNonUserCode]或[DebuggerHidden]或[DebuggerStepThrough]属性来解决问题。它没有。另一个程序员并不认为他的代码不够重要,不值得这些属性。而且,这并不是因为代码中总是隐藏着一个使用try / catch-em-all代码的错误。神奇宝贝代码。

因此微软必须找到另一种方法来帮助程序员处理糟糕的库代码。他们做到了。勾选那个复选框,bam,解决了。除了向作者发送一个令人讨厌的代码之外,你无论如何都无法对这些糟糕的代码做些什么。不要让我们或微软减慢你的速度,你们都必须相处以创造一个人们喜欢使用的产品。

答案 2 :(得分:0)

您可以使用Concord,Visual Studio附带的调试引擎(从2012版开始)。它通过一个漂亮的托管API(并且可以使用vsix技术进行部署)具有相当的可扩展性,但它没有完全记录。

Concord具有调试监视器的概念,我们可以使用IDkmDebugMonitorExceptionNotification Interface

进行挂钩

很酷的是这个界面可以监视引发的所有异常。它还可以抑制"任何检测到的异常事件,这正是我们所需要的。

我建议从Hello World样本开始:。下载它,并确保它按预期运行。

现在,只需像这样修改HelloWorld.vsdconfigxml

<!--TODO: If you copy the sample, ensure to regenerate the GUID in this file -->

<!-- 1. change component level to something higher than 40500 -->
<ManagedComponent
  ComponentId="51736b11-9fb4-4b6d-8aca-a10a2b7ae768"
  ComponentLevel="40501"
  AssemblyName="HelloWorld">

  <!-- 2. change class full name to HelloWorld.ExceptionHandler, for example -->
  <Class Name="HelloWorld.ExceptionHandler">
    <Implements>
      <InterfaceGroup>
        <NoFilter/>
        <!-- 3. change supported interface -->
        <Interface Name="IDkmDebugMonitorExceptionNotification"/>
      </InterfaceGroup>
    </Implements>
  </Class>

</ManagedComponent>

然后,只需创建一个ExceptionHandler.cs类并在其中放置类似的东西:

public class ExceptionHandler : IDkmDebugMonitorExceptionNotification
{
    private bool _unhandledDetected;

    // we're being called!
    public void OnDebugMonitorException(DkmExceptionInformation exception, DkmWorkList workList, DkmEventDescriptorS eventDescriptor)
    {
        if (_unhandledDetected)
        {
            // this will cause the program to terminate
            eventDescriptor.Suppress();
            return;
        }

        if (exception.ProcessingStage.HasFlag(DkmExceptionProcessingStage.Unhandled))
        {
            _unhandledDetected = true;
        }
        else if (exception.ProcessingStage.HasFlag(DkmExceptionProcessingStage.Thrown))
        {
            if (SuppressException(exception))
            {
                eventDescriptor.Suppress();
            }
        }
    }

    // should we suppress a thrown (1st chance) exception?
    private bool SuppressException(DkmExceptionInformation exception)
    {
        // implement any custom logic in here, for example use the exception's name
        if (exception.Name == typeof(ArgumentOutOfRangeException).FullName)
        {
            // for example, use the module (assembly) name
            var clrAddress = (DkmClrInstructionAddress)exception.InstructionAddress;
            var clrModule = clrAddress.ModuleInstance;
            if (clrModule.Name == "TheUglyOne.dll")
                return true; // we don't want this one!
        }
        return false;
    }
}

当您运行项目时,您应该看到所有异常受到监控(无论您只是我的代码&#39;和/或异常触发器设置),所以您需要什么要做的是实施一些逻辑来压制那些你真正不想看的东西。我没有检查过,但我想你可以使用自定义属性构建逻辑,因为Dkm类提供了大量的.NET元数据信息。

注意:正如您所看到的,确保程序正常终止有一些技巧。