【问题标题】:Prevent debugger to break on all Exceptions in a 3rd party library防止调试器中断第 3 方库中的所有异常
【发布时间】:2011-04-02 06:01:39
【问题描述】:

我维护了一个在递归方法调用期间内部使用异常的开源库。异常在调用堆栈中被取回并在某些情况下被处理,而在其他情况下它将返回给调用者。

我们现在遇到的问题是,一些用户正在使用“Halt on ALL exceptions”选项运行 Visual Studio 调试器,因此他们的调试器会在我们的代码正常运行时停止。

除了告诉用户禁用该设置之外,还有其他方法可以防止这种情况发生吗?比如,可能对代码应用一些属性?

【问题讨论】:

  • 你必须重写这个,否则你会收到 的仇恨邮件。

标签: .net debugging exception


【解决方案1】:

这很有可能。您需要做的就是让 Visual Studio 将相关代码视为非用户代码,然后启用“Just my调试器设置中的“代码”选项:

several ways of convincing Visual Studio that your library is not user code。一种是简单地编译没有 PDB 文件的发布版本。另一个是mark your code with DebuggerNonUserCodeAttribute

有一个演示项目展示了这些东西的实际效果: https://bitbucket.org/rstarkov/demononusercode/src – 注意 MyLibrary 中的方法是如何用非用户代码属性标记的。即使您告诉 Visual Studio 对所有异常停止“抛出”,它仍然会跳过 MyLibrary 中的异常。

对于它的价值,我不认为你的所作所为是错误的。这是正确配置调试器的问题。仅仅因为有人将他们的调试器设置为在所有事情上停止而不使用任何异常听起来并不完全正确。

【讨论】:

  • 这只是平面不适合我。该选项已设置,我装饰了班级中的所有内容,这些内容包装了不断触发中断的第 3 方 .dll。现在它只是在该代码的调用者处中断。
  • @dudeNumber4 你的意思是即使异常实际上是在被调用者内部捕获和处理的? VS 仍然会在未处理的异常上停止。尝试示例项目,看看该示例中是否跳过了异常。
  • 请注意,虽然该选项也可用于 C++,但它对异常没有影响,如下所述:msdn.microsoft.com/en-us/library/dn457346.aspx
【解决方案2】:

这是this question.的半克隆

请注意,当我使用 VS2010 时,那里建议的所有属性似乎都无法完成您的要求。

您可以做的是确保始终发送相同的自定义异常类型,即 TigraineNamespace.TigraineException,然后指示您的用户转到“异常”对话框 (Ctrl+Alt+E),单击“添加” ,编写“TigraineNamespace.TigraineException”,按 Enter,然后取消选中特定异常的复选框。

【讨论】:

  • 让我们在这里保持理性。无论如何,没有人阅读自述文件,在看到第三个异常之后,他们就不会打扰并使用另一个类似的框架:)
【解决方案3】:

不,你不能阻止它。

我建议更改您的设计以使用返回代码/类而不是异常。异常对于递归方法调用来说是非常昂贵的。

【讨论】:

    【解决方案4】:

    我不相信有任何方法可以阻止“所有异常停止”这样做。

    除了告诉用户禁用该设置之外,还有什么方法可以防止这种情况发生吗?

    只有避免将异常用于非错误处理目的(根据您的描述,听起来您的库几乎违反了此准则)。

    【讨论】:

    • 实际上,我认为这里的指南有问题。这里的问题:我正在递归地遍历类依赖树,如果无法满足路径中的一个依赖项,则异常是提供良好事件来源的唯一好方法。异常可能会一直冒泡到调用者,但如果通过依赖图有另一个可满足的路径,它也可以在框架内部处理。
    • 必须有办法做到这一点。我以前从未见过自己闯入框架代码,而且我用过很多。例如,ASP.NET 在调用 Response.End 时会抛出 ThreadAbortException ..
    • @Tigraine:我不同意,一个触底的递归方法可以返回成功/失败以及值。如果分支失败,则该值包含详细信息。考虑一下如何在没有异常和没有 longjmp(或其他非本地 goto)的情况下做到这一点。
    • @Richard:对于这种简单的情况,这意味着将结果包装在另一个 BlaBlaResult 对象中。像 NHibernate 这样一直处理底层 SQLExceptions 的框架(包装它们以重新抛出或作用于它们)呢?在某些用例中,您只需等待底层的东西失败,然后再做一些事情。
    • @Tigraine “听起来你没有使用它来解决错误”。来自数据库的错误是异常的(不会故意导致数据库错误)。如果它们是真正的错误,那么例外是好的。如果不是(例如,未能匹配这条路径,所以尝试另一个:当这是预期的搜索行为时)那么异常可能是错误的方法。但这是你的代码。如果您使用异常并且您的用户想要中断调试器中的所有异常,那么他们会看到很多中断。你的选择,你必须做出取舍。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-07
    • 1970-01-01
    • 1970-01-01
    • 2011-12-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多