.NET源代码可以对调试断点进行硬编码吗?


71

我正在寻找.NET(尤其是C#,尤其是C#)中的.NET(尤其是C#)来触发调试中断,就像在该点处设置了断点一样,而不必记住在调试器中设置特定的断点,而不影响生产运行时间。

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

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

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

更新:虽然ctacke的答案最符合我的需求,但此后我也发现了Debug.Assert()的窍门-在调试器中运行时-暂停调试器,转到调试代码。断言待处理的呼叫(由于在框架代码中处于绿色状态,因此以绿色突出显示),然后单击“跳出”(shift-F11),然后在断言对话框中单击“忽略”。这将使调试器在断言返回时暂停(并且可以继续执行,就好像它没有发生一样,因为它被忽略了)。可能还有其他方法可以做很多相同的事情(点击Retry可以更直接地做到这一点吗?),但是这种方法很直观。

Answers:


131

您可能正在执行以下操作:

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

当然,这仍将在Release版本中进行编译。如果您希望它的行为更像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();
    }

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


2
您还可以使用#if DEBUG ... #endif代替
Steven A. Lowe

11
可以,但是它比有条件的丑陋得多,因为您还必须使用precompiler指令包装对方法的每次调用。
ctacke

2
为了澄清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.
起见

12

System.Diagnostics.Debugger.Break


(最初在08年12月回复,这是我知道自己可以对自己的问题的答案发表评论之前的另一个答案):啊,谢谢,shahkalpesh。System.Diagnostics.Debugger.Break()是一个好的开始!这就是我在调试器下而不是调试下所缺少的。看起来那样会中断并要求附加调试器,我可能想避免这种情况。但是它看起来像... if(Debugger.IsAttached)Debugger.Break(); ...按照ctacke的建议做我想要的东西。Debugger.Launch()可能适用于稍有不同的情况,如果还没有调试器,则需要调试器。
罗伯·帕克

10

如果您只需要一行代码而不是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版更改。
谢尔盖(Sergey)

即使[DebuggerHidden]这样做(确实会阻止您进入),Debugger.Break仍然会绕过它并停在那儿,可悲的是。
jeromej

9

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

System.Diagnostics.Debugger.Break();

但这确实

System.Diagnostics.Debugger.Launch();

如果未附加调试器,则首先需要将其附加到Debugger.Launch(),然后可以使用Debugger.Break()。如果要调试一个进程启动另一个进程并且要调试两个进程的解决方案,则这是必需的。
安迪·B。

4

即使只吞下Visual Studio,将其配置为与调试器一起弹出怎么办?

做这个:

  • 转到调试->异常...
  • 找到合适的例外,如果是您自己的,则添加它
  • 选中“引发”复选框以查找异常

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

您可以在此处查看更多信息。


这是一个值得一提的技巧。这对于确定问题首次发生的位置(并仍然获取成员状态,而不仅仅是异常堆栈跟踪?)特别有用。但是,在这种情况下,我希望消息来源提醒我们注意我们不是特别希望发生且无法为其设置的异常。
罗伯·帕克

4

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


很酷的把戏。当然,对系统异常没有好处,但是我们可以尝试使用自己的Exception类型,以一个或两个静态成员为条件,以便我们可以打开和关闭它,并检查Debugger.IsAttached; 即使没有IsAttached,一种设置也可以使用Break()/ Launch(),而另一种设置则可以。
罗伯·帕克

1

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


嗯,谢谢。下次在调试器中命中一个断言时,我将不得不尝试一下。对于“重试”是什么意思,我从来都不清楚。也许这是该对话框过去使用的遗留物。
罗伯·帕克

1
当然,这是一个措辞不佳的对话框。
阿伦·坎布雷
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.