跳转到当前光标处(Ctrl+F10)我经常看到有人为了到达目标代码位置,在程序的早期设置断点,然后反复按F10/F11,一步一步到目标代码。当程序员确实需要仔细观察每一步的状态变化时,F10/F11是一个合理的选择。然而,在大多数情况下,人们只是想快速到达他们真正关心的代码。这时候F10/F11就不是最好的选择了。这时,你应该使用“跳转到当前光标”功能。先把光标定位到要测试的目标代码行,然后同时按下Ctrl和F10,被测程序会直接跳到这一行停止。您不必再多次按F10/F11。即使目标代码在单独的类或方法中,您仍然可以从当前检查的地方跳转。另一种常见的条件中断情况是开发人员设置断点,运行程序,使用不同的输入触发断点,然后在断点处手动检查是否满足某些特定条件,从而决定是否继续调查。如果当前场景不是他们想要的,按F5继续运行程序,尝试其他输入,手动重复这个过程。针对以上情况,VisualStudio提供了一个更方便的功能——“条件中断”。只有当程序满足开发者预设的条件时,条件断点才会被触发,调试器才会中断。这样就可以避免频繁的人工检查/恢复程序运行,大大减少调试过程中的人工繁琐工作。如何设置条件断点设置条件断点非常简单。在特定行上,按F9设置断点。然后右击断点——编辑窗口左侧的红点,在上下文菜单中选择“Condition…”。弹出一个对话框供您设置激活断点所需的条件。例如:我们希望只在局部变量paginatedDinners的大小小于10时中断。现在我再次运行这个程序来实现查找。只有当返回值小于10时,程序才会中断。对于大于10的值,将跳过断点。记录到达断点的个数有时候你想在第N次满足条件的执行到断点时才中断程序的执行。例如:当第5次返回小于10餐的查询结果时,中断程序的执行。这可以通过右键单击断点并在弹出菜单上选择“Hitcount...”菜单命令来完成。这时系统会弹出一个对话框,让你指定:(1)当满足条件且累计进入断点的次数等于N时,断点命一次。(2)当满足条件且累计进入断点的次数为N的倍数时,断点命一次。(3)当满足条件且累计进入断点的次数大于N时,每次都命断点。机器/线程/进程过滤设置如下:右击断点;在弹出菜单中选择“过滤器...”菜单命令;然后指定命中断点的具体条件:在指定的机器上,或者在指定的进程中,或者在线程中指定。Trackpoints-输入断点时的自定义操作许多人不知道调试功能“TrackPoints”。“跟踪点”是一种特殊的断点,当它被击中时,会触发一系列自定义操作。如果您想在不中断调试的情况下观察程序的行为,则此功能特别有用。我将使用一个简单的控制台程序来演示如何使用“跟踪点”。下面是斐波那契数列的递归实现:在上面的程序中,我们使用Console.WriteLine()来输出针对特定输入值生成的最终斐波那契数列。如果你想在操作中观察每次递归操作后的数字序列而不实际破坏调试器中的程序怎么办?“跟踪点”可以很容易地实现。要设置轨迹点,您可以通过在特定行上按F9来添加轨迹点。然后右击断点,在上下文菜单中选择“WhenHit...”:在弹出的对话框中,可以设置断点被击中时触发的事件。在上面的示例中,我们设置了一旦命中断点就打印的跟踪信息。请注意,我们已将局部变量“x”的值作为跟踪信息的一部分输出。局部变量可以通过{变量名}语法输出。也可以使用系统自带的命令($CALLER、$CALLSTACK、$FUNCTION等)在跟踪信息中输出常用的调试值。在上面的例子中,我们还选择了最下方的“继续执行”选项,意思是我们不希望程序中断调试状态,而是继续运行。唯一不同的是:每次满足断点条件,都会输出我们自定义的trace信息。现在我们运行程序,会发现自定义的跟踪信息自动显示在VisualStudio的“输出”窗口中。这使得我们很容易看到程序的递归调用过程:您也可以选择为应用程序添加一个自定义的跟踪信息监听器。这时候trace点的输出信息就会通过它输出,而不是VisualStudio的“Output”窗口。Tracepoints-RunningCustomMacros上周我在伦敦演讲时,一位听众问:是否可以在命中tracepoint时自动输出所有局部变量?VisualStudio中没有这样的内置功能,但我们可以编写自定义宏来实现它,然后在命中跟踪点时调用该宏。这个的实现需要打开VisualStudio的宏编辑器(Tools->Macro->MacroIDE菜单命令),然后在projectexplorer的MyMacros节点下选择一个模块或者新建一个模块(比如:添加一个名为“UsefulThings”模块的文件),然后将以下VB宏代码粘贴到模块中并保存。SubDumpLocals()DimoutputWindowAsEnvDTE.OutputWindowoutputWindow=DTE.Windows.Item(EnvDTE.Constants.vsWindowKindOutput).ObjectDimcurrentStackFrameAsEnvDTE.StackFramecurrentStackFrame=DTE.Debugger.CurrentStackFrameoutputWindow.ActivePane.OutputString(“*DumpingLocalVariables*”+vbCrLf)ForEachexpAsEnvDTE.ExpressionIncurrentStackFrame.LocalsoutputWindow.ActivePane.OutputString(exp.Name+”=”+exp.Value.ToString()+vbCrLf)NextEndSub上面的宏代码会循环当前堆栈并将所有局部变量输出到“输出”窗口。使用自定义的“DumpLocals”宏那么,我们就可以在下面这个简单的程序中使用新自定义的“DumpLocals”宏了:在上面的代码中,我们使用F9在“Add”方法的返回值处添加断点,然后对-单击断点,然后从弹出菜单中选择“命中时”。将显示以下对话框。与之前不同的是,我们没有选择“Printamessage”选项,也没有手动设置需要输出的变量;相反,选择“运行宏”复选框并将其分配给我们在上面创建的UsefulThings.DumpLocals宏:为了让程序在命中跟踪点后继续运行,我们将继续选中“继续执行”复选框。运行程序现在按F5运行程序,当“Add”方法被调用时,我们将在VisualStudio的“Output”窗口中看到如下结果。请注意,当命中跟踪点时,宏将自动列出每个局部变量的名称和值:总结VisualStudio的调试器功能极其丰富,我强烈建议您花时间掌握它的所有功能。上面的提示只是人们通常很少注意的一些功能。我以前写过关于VS2010调试器改进的博客(包括固定数据提示、导入/导出断点、保留变量的最后值等)。以后我将在博客中详细介绍VS2010的新IntelliSense和文件调试信息的转储支持。这些技术赋予了开发者强大的调试能力,使调试程序(包括发布后的产品)变得更加简单和强大。
