Visual Studio调试器提示& .NET的技巧

时间:2008-10-14 14:43:13

标签: .net visual-studio debugging hidden-features

我已经和VS的调试器一起工作多年了,但我偶尔会遇到一个我以前从未注意过的功能,并且想想“该死的!我怎么能错过它?它是如此有用!“

[免责声明:这些提示适用于VS 2005中的C#项目,不保证VS或其他语言的旧版本]

跟踪对象实例

使用给定类的多个实例?你怎么能分开他们? 在垃圾收集前编程时,很容易跟踪引用 - 只需查看内存地址即可。使用.NET,你不能这样做 - 对象可以移动。 幸运的是,通过手表视图,您可以右键单击手表并选择“创建对象ID”。

  
    

watches view http://img403.imageshack.us/img403/461/52518188cq3.jpg

  

这会在实例的值之后附加{1#},{2#}等,从而有效地为实例提供唯一标签。它看起来像这样:

  
    

numbered instance http://img383.imageshack.us/img383/7351/11732685bl8.jpg

  

标签在该对象的生命周期内保持不变。

监视变量的有意义值

默认情况下,监视变量的值是它的类型。如果你想看到它的字段,你必须扩展它,如果有很多字段或它们做了一些复杂的事情,这可能需要很长时间(甚至超时!)。

但是,某些预定义类型显示更有意义的信息:

  • 字符串显示其实际内容
  • 列表和词典显示其元素数量等。

meaningful info http://img205.imageshack.us/img205/4808/37220487md1.jpg

为我自己的类型拥有它不是很好吗?

嗯...

...使用.NET Reflector的一些高质量时间显示了使用我的自定义类型上的DebuggerDisplay属性轻松完成此操作:

[System.Diagnostics.DebuggerDisplay("Employee: '{Name}'")]
public class Employee {
    public string Name { get { ... } }
    ...
}

...重新开始,......

ta da! http://img60.imageshack.us/img60/926/79816018ha1.jpg

此处有关于此主题的更多信息:MSDN

中断所有例外

...甚至是代码中处理的那些! 我知道,自从我出生以来,我就是一个不知道这件事的人,但无论如何它仍然存在 - 也许有一天这会对某人有所帮助:

每次抛出异常时,您都可以强制调试进程进入调试模式。曾经花了几个小时寻找一个只是为了遇到这样的代码吗?

try {
    runStrangeContraption();
} catch(Exception ex) {
    /* TODO: Will handle this error later */
}

在这些情况下捕获所有异常非常方便。 这可以从 Debug>启用。例外...(Ctrl-Alt-E)。勾选“Thrown”列中的框,了解您需要的每种类型的异常。


这对我来说是一些前额拍打的时刻。 你愿意和你分享吗?

14 个答案:

答案 0 :(得分:19)

try {
    // do something big
}
catch {
    // breakpoint set here:
    throw CantHappenException("something horrible happened that should never happen.");
}

您如何看待最初抛出的异常?在观察窗口中,输入$ exception

答案 1 :(得分:17)

这是我学到的另一个巧妙的技巧:

System.Diagnostics.Debugger.Break()

以编程方式使调试器在下一条指令上中断。 真的很好的部分是,这也适用于以发布模式编译的程序,没有调试信息。

答案 2 :(得分:12)

我总是确保在我创建的新线程上设置“Name”属性。这样,当我调试时,我可以更容易地识别不同的线程。

答案 3 :(得分:9)

当然,请查看当天的VS提示:

http://blogs.msdn.com/SaraFord/

答案 4 :(得分:7)

我的一些人

  • 取消选中工具 - >选项 - >调试中的“启用我的代码”选项。
  • 有条件的断点 - 他们几乎每天都能挽救我的生命
  • 如果事情变得丑陋,
  • Use the .NET framework source

答案 5 :(得分:7)

两个代码内的技巧:

我非常喜欢System.Diagnostics.DebuggerStepThrough属性;您可以将它附加到类,方法或属性,以使VS在调试时默认不输入代码。我比DebuggerHidden属性更喜欢它,因为如果你真的需要调试它,它仍然允许你在被忽略的代码中放置断点。

另一个(有时)有用的电话是System.Diagnostics.Debugger.Launch();当执行命中时,您将看到“选择调试器”对话框,调试器将启动。有点粗鲁,但有用,特别讨厌附加到进程,比如由另一个进程生成的进程并立即执行您的代码。

答案 6 :(得分:6)

立即窗口中的

.load sos:)

答案 7 :(得分:4)

工具 - >附加到进程 - 容易忘记,但有了它我可以在网页中调试脚本,在另一个进程中加载​​托管代码(想想加载项模型),甚至是非托管代码。小心让它自动选择你感兴趣的调试类型。

跟踪点(和其他断点功能......右键点击断点并享受乐趣)! - http://blogs.msdn.com/saraford/archive/2008/06/13/did-you-know-you-can-use-tracepoints-to-log-printf-or-console-writeline-info-without-editing-your-code-237.aspx

即时窗口非常棒。

如果您部署应用程序(并且可以访问可以重现问题的计算机),

Remote Debugging非常有用。

还有更多。尝试进入WinDbg和SoS!

答案 8 :(得分:4)

我发现模块窗口很多次都很有用。它告诉调试器是否加载了所需的dll以及加载了哪个版本的dll。它还允许您手动加载或卸载DLL。

答案 9 :(得分:3)

如果你的代码重复很多但只在一组特定的条件下失败,例如循环中的代码,从循环中调用的方法或从多个线程调用的方法,则条件中断非常有用。将break语句放在感兴趣的行上并设置其条件以匹配错误情况。 (有一个简单的例子here。)

答案 10 :(得分:2)

我的两个: 一个我希望每个人都到处使用的那个:

Debug.Assert(<condition>, <message>)

第二个DebuggerHidden:

<DebuggerHidden()> _
Public Sub ReadDocumentProperty(ByVal propertyName As String, ByRef PropVal As Integer, ByVal DefaultVal As Integer)
    Try
        Dim prop As Office.DocumentProperty
        prop = CustomProps.Item(propertyName)
        PropVal = CType(prop.Value, Integer)
    Catch
        PropVal = DefaultVal
    End Try
End Sub

即使您设置了Debug,Exceptions,Break on thrown exception set,也不会捕获此处的异常。

答案 11 :(得分:1)

创建一个宏以附加到进程并分配给未使用的键盘快捷方式。比去快得多:debug - &gt;附加到流程 - &gt;在流程列表中搜索流程 - &gt; ...

答案 12 :(得分:1)

如果设置IDE在发生异常时将其分解,即使我们没有任何调试点集也是如此。

调试 - &GT;例外 - &gt; Commmon语言运行时异常 - &gt;抛出

这使得查找隐藏的异常处理问题变得轻而易举。实际上,这是每个开发人员应该在开发过程中设置的一种设置,以避免任何无法处理或甚至处理下面的异常。

答案 13 :(得分:0)

在非托管代码中,您可以设置“数据断点”。他们使用CPU的调试寄存器来发出INT3,调试器在运行时没有开销就停止在该指令上(在旧版本中,调试器逐步通过程序检查内存.....慢!)

如果你在knwon地址有一些损坏(堆栈/堆可变得破坏),这很有用。

还可以自定义ide \ packages \ debugger中的AutoExp.dat以显示您的数据结构。

指针,mb在监视窗口中显示十六进制转储 http://msdn.microsoft.com/en-us/magazine/dd252945.aspx

百胜