对另一个断点的条件使用一个断点的命中计数

时间:2011-12-07 23:36:07

标签: visual-studio-2008 debugging conditional-breakpoint

我在C#代码上使用Visual Studio 2008。

如果另一个断点被击中(并打破了),我想只在断点处断开。有没有办法做到这一点?

我认为作为子问题,访问调试器所具有的信息会很好。

这个的基本原理是我感兴趣的是只在给定某个callstack的某个断点处(以及在callstack中执行其中一个函数的某个点)。也许我应该使用callstack代替?另一个原因是,以编程方式访问调试器知道的内容会很有趣。

感谢。

1 个答案:

答案 0 :(得分:7)

使用局部变量

创建这样的条件断点的最简单方法是创建一个新的线程静态变量(如果它应该是全局的,则只是静态变量)。假设我们的代码如下所示:

class Program
{
#if DEBUG
    [ThreadStatic]
    static int breakVariable = 0;
#endif

    static void Main(string[] args)
    {
        TestMethod2();

        TestMethod1();
        TestMethod2();

        TestMethod2();

        TestMethod1();
        TestMethod2();
    }

    static void TestMethod1()
    {
        Console.WriteLine("test1");
    }

    static void TestMethod2()
    {
        Console.WriteLine("test2");
    }
}

现在假设您在Console.WriteLine("test1");上设置了breakpoint1,在Console.WriteLine("test2");上设置了breakpoint2。只有当breakpoint1被击中2次时,你才想在breakpoint2处中断。在这种情况下,您需要将breapoint1的Hit Count...属性设置为break when the hit count is equal to 2。然后在When Hit...属性检查Print a message和文本框中输入:{breakVariable = 1}

when break

然后将breakpoint2的属性Condition...设置为breakVariable == 1并检查Is true

condition

如果您希望breakpoint2在被点击后变为非活动状态,您可以再次使用When Hit...属性将其Print a message值设置为{breakVariable=0}

使用宏

这种方法要困难得多,特别是如果你不喜欢VBA(像我:) :)但你可能会感兴趣,因为它不需要对应用程序代码进行任何更改。我们定义两个宏:

Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports EnvDTE90a
Imports EnvDTE100
Imports System.Diagnostics

Public Module Module1

    Public Sub SetMyBreakpoint()
        Dim bps As EnvDTE.Breakpoints
        bps = DTE.Debugger.Breakpoints.Add(File:="C:\MyProject\ConsoleApplication1\Program.cs", _
                                           Line:=25)
        Dim bp As EnvDTE80.Breakpoint2
        For Each bp In bps
            bp.Tag = "mytag"
            ' Add this line only if you want the breakpoint to be removed on hit
            ' Although I don't know why - it does not always worked :(
            bp.Macro = "Macros.MyMacros.Module1.RemoveMyBreakpoint"
        Next
    End Sub

    Public Sub RemoveMyBreakpoint()
        Dim bp As EnvDTE.Breakpoint
        For Each bp In DTE.Debugger.Breakpoints
            If (bp.Tag = "mytag") Then
                bp.Delete()
            End If
        Next
    End Sub
End Module

现在,对于breakpoint1,您仍然需要像以前一样设置Hit Count...属性,但现在在When Hit...属性中,而不是检查Print a message检查Run a macro并选择{{ 1}}程序。在SetMyBreakpoint方法和正确的行中提供代码文件的完整路径非常重要(您可以检查API以找到设置断点的其他方法,例如在函数上代替代码文件)。这里有一个小警告 - 我发现自动删除第二个断点并不总是有效 - 但也许是我的Visual Studio。

使用调用堆栈

您可以再次使用断点的Breakpoints.Add属性 - 查看this question以查找详细信息。