如何在 VS2015 的断点条件表达式中使用 Environment.StackTrace

How to use Environment.StackTrace in a conditional expression for a breakpoint in VS2015

我正在尝试调试一个问题,如果我可以在 属性 的 getter 中设置一个断点,那将非常有帮助,但我不需要每次都中断是从我的 UI 中某个按钮的 CanExecute 调用中调用的。我的想法是我可以简单地在不包含该字符串的调用堆栈上设置断点,但这似乎不起作用。我能想到的最好的解释方法是使用设置图像和命中断点的输出。

如图所示,断点的条件设置在命中时直接输出,在输出中您可以看到它被命中了几次 .get(): true - 正确。但是,当它截取此屏幕截图时,条件为假,如输出所示。程序因断点被错误地击中而停止。

我是不是做错了什么——这可能吗?在我看来像是 VS2015 中的一个错误,输出可以正确评估 bool,为什么断点条件不能这样做?

编辑,为图像添加注释以防它在某个时候丢失。 我在 属性 的 get 方法中有一个断点,它只是 returns 基础字段。断点设置显示断点上有一个定义断点的条件,它只应在表达式 !Environment.StackTrace.Contains("CanExecute") returns 为真时命中,即仅在 Stack Trace 不包含 [= 时中断25=] 字符串。 断点设置的 Action 部分只是使用 $FUNCTION: {!Environment.StackTrace.Contains("CanExecute")} 输出函数名和条件表达式。动作设置为不继续执行。

我不知道为什么堆栈跟踪信息在断点条件下不可用,但是有一个疯狂的 workaround/hack 你可以作为 another answer[= 中概述的技术的扩展来做28=]

如果你使用自动属性,它不会像"cleanly"那样工作,因为它需要两个断点,而自动属性只有一个点来绑定断点但我想这对自动 属性 无论如何都没有用。


将第一个断点放在 get 方法的左花括号上(将光标放在花括号上并按 F9)。在此断点上设置一个动作;将 "Log a message to Output Window:" 设置为

{System.AppDomain.CurrentDomain.SetData("break", !Environment.StackTrace.Contains("CanExecute"))}

并确保选中 Continue execution

将第二个断点放在 return 语句上(将光标放在花括号上并按 F9)。在此断点上设置条件:

(bool)System.AppDomain.CurrentDomain.GetData("break")

根据您的格式,这可能需要 "Breakpoints" window Debug > Windows > Breakpoints (Ctrl+Alt+B) 的帮助,以防花括号和 return 语句在同一行.您可以通过右键单击 "Breakpoints" window 中的断点并选择 Settings

来编辑 action/condition

需要强制转换为 bool,因为 GetData() returns 和 object 并且条件断点不会为您执行强制转换。


它不是很漂亮,并且由于全局状态,它在多线程环境中不能很好地工作,但它在紧要关头很有用。如果您以这种方式需要多个 "conditional breakpoints",请确保在 SetData()/GetData().

中使用不同的密钥

但是,如果可以的话,通常(取决于您的编译时间和对代码与调试符号的访问)quicker/easier 只是临时编辑代码以放置您想要中断的条件。

例如

public Foo Selected
{
    get
    {
        if (!Environment.StackTrace.Contains("CanExecute"))
            System.Diagnostics.Debugger.Break();

        return _selected;
    }
}

*在auto属性的情况下,可以在属性访问前的CanExecute()方法中使用一对动作断点将"break"设置为true,然后在属性访问后将 "break" 设置为 false,并为条件使用

(bool?)System.AppDomain.CurrentDomain.GetData("break") != false

以确保它在 CanExecute() 之前和之后仍会中断,但不会在

期间中断