【问题标题】:Can .NET source code hard-code a debugging breakpoint?.NET 源代码可以硬编码调试断点吗?
【发布时间】:2010-09-26 13:31:35
【问题描述】:

我正在寻找一种在 .NET(尤其是 2.0,C#)中为源代码触发调试中断的方法,就好像在该点设置了一个断点,而不必记住在调试器,并且不干扰生产运行时。

我们的代码需要吞下生产中的异常,因此我们不会破坏链接到我们的客户端应用程序,但我正在尝试对其进行设置,以便在碰巧运行时弹出此类错误以进行分析在调试器中,否则将被安全地忽略。

我使用Debug.Assert(false) 的尝试并不理想,我假设Debug.Fail() 的行为方式相同。从理论上讲,它在生产中应该没有影响,并且在调试时确实会成功停止,但是根据设计(据我所知),如果您想忽略该错误,则无法继续执行,就像使用实际断点一样,就像我们在生产中吞下错误一样。它显然也破坏了对变量状态的评估,因为调试器实际上在本机系统代码中停止,而不是在我们的系统代码中,所以它的调试帮助是有限的。 (也许我错过了一些重新审视事物以查看变量等发生的地方的方法。???)

我希望有类似 Debug.Break() 的东西,但它似乎不存在(除非可能在更高版本的 .NET 中?),而且似乎也没有其他 Debug 方法适用。

更新:虽然 ctacke 的答案是我所寻找的最佳匹配,但我还发现了 Debug.Assert() 的一个技巧——在调试器中运行时——暂停调试器,转到待处理的 Debug.Assert 调用代码(以绿色突出显示,因为它在框架代码中已关闭)并点击 Step-Out (shift-F11),然后在断言对话框中点击 Ignore。这将使调试器在断言返回时暂停(并且能够继续执行,就好像它没有发生一样,因为它被忽略了)。可能还有其他方法可以做很多相同的事情(点击重试会更直接吗?),但这种方法很直观。

【问题讨论】:

    标签: c# visual-studio .net-2.0 breakpoints


    【解决方案1】:

    System.Diagnostics.Debugger.Break?

    【讨论】:

    • (最初在 08 年 12 月作为另一个答案回复,然后我才知道我可以对自己问题的答案发表评论):啊,谢谢,shahkalpesh。 System.Diagnostics.Debugger.Break() 是一个好的开始!这就是我在调试器而不是调试下所缺少的。看起来这会中断并要求附加一个调试器,我可能想避免这种情况。但它看起来像...... if (Debugger.IsAttached) Debugger.Break(); ...按照 ctacke 的建议,做我正在寻找的东西。 Debugger.Launch() 可能适用于稍微不同的位置,如果还没有调试器,您需要一个调试器。
    【解决方案2】:

    我曾经遇到过这种情况不起作用

    System.Diagnostics.Debugger.Break();
    

    但确实如此

    System.Diagnostics.Debugger.Launch();
    

    【讨论】:

    • 如果没有附加调试器,那么您首先需要使用 Debugger.Launch() 附加它,然后您可以使用 Debugger.Break()。如果您想调试一个解决方案,其中一个进程启动另一个进程并且您想同时调试这两个进程,则这是必要的。
    【解决方案3】:

    你可能正在追求这样的东西:

    if(System.Diagnostics.Debugger.IsAttached)
      System.Diagnostics.Debugger.Break();
    

    当然,它仍然会在发布版本中编译。如果您希望它的行为更像 Debug 对象,其中代码根本不存在于 Release 构建中,那么您可以执行以下操作:

        // Conditional("Debug") means that calls to DebugBreak will only be
        // compiled when Debug is defined. DebugBreak will still be compiled
        // even in release mode, but the #if eliminates the code within it.
        // DebuggerHidden is so that, when the break happens, the call stack
        // is at the caller rather than inside of DebugBreak.
        [DebuggerHidden]
        [Conditional("DEBUG")] 
        void DebugBreak()
        {
            if(System.Diagnostics.Debugger.IsAttached)
                System.Diagnostics.Debugger.Break();
        }
    

    然后在您的代码中添加对它的调用。

    【讨论】:

    • 你也可以使用 #if DEBUG ... #endif 代替
    • 当然,但它比条件更难看,因为您还必须使用预编译器指令包装对方法的每次调用。
    • 澄清一下,来自 MSDN:When a method marked as conditional is called, the presence or absence of the specified preprocessing symbol determines whether the call is included or omitted. If the symbol is defined, the call is included; otherwise, the call is omitted. 以及 A conditional method must be a method in a class or struct declaration and must have a return type of void.
    【解决方案4】:

    即使你吞下它,只需将 Visual Studio 配置为弹出调试器怎么样?

    这样做:

    • 转到调试->异常...
    • 找到正确的例外,如果是您自己的,也可以添加
    • 选中“抛出”复选框以查找异常

    这将在引发异常的位置停止 Visual Studio,而不仅仅是在未处理的情况下。

    您可以查看更多信息here

    【讨论】:

    • 这是一个值得一提的技巧。它特别有助于确定问题首先出现的位置(并且仍然获得成员状态,而不仅仅是异常堆栈跟踪?)。但在这种情况下,我希望消息来源提醒我们注意我们没有特别期望发生且无法设置的异常。
    【解决方案5】:

    我发现一个不错的技巧是将 Debugger.Break() 放在异常的 ctor 中。

    【讨论】:

    • 很酷的把戏。当然,对系统异常没有好处,但我们可以尝试使用我们自己的异常类型,以一个或两个静态成员为条件,以便我们可以打开和关闭它,同时检查 Debugger.IsAttached;即使没有 IsAttached,一种设置也可以 Break()/Launch(),另一种只有在它存在的情况下。
    【解决方案6】:

    在 Visual Studio 2010 中,在 Debug.Assert 对话框中点击 Retry 会将您带到失败的调试断言,就像您有一个断点一样。

    【讨论】:

    • 嗯,谢谢。下次我在调试器中遇到断言时,我必须尝试一下。我一直不清楚“重试”应该是什么意思。也许这是该对话框过去使用的保留。
    • 这肯定是一个措辞不佳的对话。
    【解决方案7】:

    如果你想只有一行代码而不是 4 行,换行

    #if DEBUG
           if (Debugger.IsAttached)
                Debugger.Break();
    #endif
    

    进入

    public static class DebugHelper
    {
        [DebuggerHidden]
        [Conditional("DEBUG")]
        public static void Stop()
        {
           if (Debugger.IsAttached)
                Debugger.Break();
        }
    }
    

    并使用

    DebugHelper.Stop();
    

    已添加DebuggerHiddenAttribute 以防止调试器在Stop 方法的内部代码上停止并使用F11 单步执行该方法。

    【讨论】:

    • +1 表示[DebuggerHidden] 的建议和解释;这将使条件编译的方法更加方便。你知道这个属性被支持多久了吗?它是不是有点新,或者它甚至可以回到 .NET 2.0 和 VS 2010 左右?
    • 甚至从 1.0 开始 - 早于 Debugger.Break() 的引入。 msdn.microsoft.com/library/… 值得注意的是,对于未附加调试器的情况,方法 Break() 的行为已从 4.0 版更改。
    • 即使使用[DebuggerHidden](这确实会阻止您介入),Debugger.Break 仍然会绕过它并停止,好吧,可悲的是。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-24
    • 1970-01-01
    • 2012-04-14
    • 1970-01-01
    • 1970-01-01
    • 2021-04-20
    相关资源
    最近更新 更多