如何从 Debugger.GetExpression 获取 DisplayString 字段?

Posted

技术标签:

【中文标题】如何从 Debugger.GetExpression 获取 DisplayString 字段?【英文标题】:How can I get the DisplayString field from Debugger.GetExpression? 【发布时间】:2020-10-06 21:16:19 【问题描述】:

背景

我正在用 C# 编写一个 Visual Studio 扩展,它在调试另一个应用程序时在即时窗口中执行代码。该表达式返回的值可以是 int、字符串文字、类等。我正在调试的应用程序是用 C++ 编写的。

代码

要执行即时窗口命令,我使用这行代码:

var expression = dte.Debugger.GetExpression("funcname()");

并检索我使用的结果:

string val = expression.Value;

和:

var children = expression.DataMembers;

这是我正在调试的应用程序中的 myFunc():

std::vector<int> myFunc()

    return  1, 2, 3, 4, 5 ;

问题

当我在即时窗口中手动运行表达式时,返回的对象被转储,因为我在监视窗口中看到它 (see here)。我设法找到了所有孩子的名字,但缺少值 (see here)。

我想要的是实现DisplayString( size=5 ),但我还没有发现任何有用的东西。

编辑:我不必使用这个 API。如果您知道另一种可以返回此刺痛的方法,请提出建议。一种想法可能是检索即时窗口 (see the right side) 的完整输出字符串,然后对其进行解析。

EDIT2:See this video that better explains the issue

【问题讨论】:

您好,您好,如果您在观看窗口中单击“下拉”键(展开列表),在string val= expression.Value; 旁边,就像您分享的屏幕截图一样,它会显示size=5吗?跨度> @Lance 不幸的是expression.Value 返回一个字符串,所以你在第二个屏幕截图中看到的就是我得到的。我试图检查expression 变量,但Value 是唯一有意义的属性。其他可用的属性是TypeNameDataMembers,但它们都不包含 size=5 。还有一个名为Collection 的属性,但它始终为空,我认为这不是我问题的解决方案。让我发疯的是 DataMembers 的名称跟随着可视化工具。它们的 value 属性也有同样的问题。 嗨,松懈,我检查了这个文档:std:Vector,我注意到size 是 std:Vector 的成员函数。而且我认为表达式的属性不能直接得到size 嗨佩里,感谢您的评论。我认为我没有很好地解释问题是什么:我在监视窗口或即时窗口中看到的与我从 GetExpression 获得的不同。 size=5 是可视化工具文件 (.natvis) 中定义的显示字符串。如果 GetExpression 无法获得 size 的值,则整个自定义可视化工具将失败,因此将使用默认可视化工具。另一方面,如果您查看expression.DataMembers,您将看到这些元素与自定义可视化工具相匹配。 对不起,不要介意那个 GitHub 链接。我没有仔细阅读。这是正确的示例:docs.microsoft.com/en-us/visualstudio/debugger/…(参见“Natvis 视图”段落中代码的 XML sn-p) 【参考方案1】:

你使用向量变量来获取/解析函数返回值,这是合理的,因为myFunc()的返回结果正是向量类型,因此变量“std::vector result”可以解析得到向量对象正确。 “在即时窗口中手动运行表达式,返回的对象被转储,就像我在观察窗口中看到的那样”是什么意思?

同时,EnvDTE.Expression.Value 是表示对象值的字符串。它与显示字符串‘ size=5 ’无关,它只是一个属性表达式。您可以使用以下示例代码打印它:

public static void Value(DTE dte)  
  
    // Setup debug Output window.  
    Window w = (Window)dte.Windows.Item(EnvDTE.Constants.vsWindowKindOutput);  
    w.Visible = true;  
    OutputWindow ow = (OutputWindow)w.Object;  
    OutputWindowPane owp = ow.OutputWindowPanes.Add("Value property: ");  
    owp.Activate();  

    EnvDTE.Expression exp = dte.Debugger.GetExpression("tempC", true, 1);  
    owp.OutputString("\nThe name of the expression: " + exp.Name);  
    owp.OutputString("\nThe type of the expression: " + exp.Type);  
    owp.OutputString("\nThe value of the expression: " + exp.Value);  

因此,我们无法从此处的即时窗口获取“size=5”应该是设计使然:

关于“可视化文件(.natvis)中定义的显示字符串”,DisplayString应该是自定义的属性,能否提供您的可视化文件(.natvis),或者可以重现问题的示例项目?

【讨论】:

您好,非常感谢您的回答。当我尝试创建一个演示项目来重现该问题时,我终于在我的代码中找到了问题所在!诀窍是将true 放入dte.Debugger.GetExpression("tempC", true)!现在expression.Value 按预期计算为" size=5 " 关于你的问题,我将解释我的意思是“在即时窗口中手动运行表达式,返回的对象被转储,因为我在监视窗口中看到它”。查看第一次编辑中的图像:我在目标应用程序的断点处打开了左侧的监视窗口和右侧的即时窗口。如您所见,即时窗口中写入的信息与监视窗口中写入的信息相同,甚至是“ size=5 ”(这是我要查找的内容)。问题是 dte.Debugger.GetExpression("tempC").Value".." 如果你编辑你的答案,我会接受它作为最终答案:只要说问题是缺少true,如果可以的话,说出它的作用(我听不懂它来自official docs)。再次感谢您!【参考方案2】:

我发现了问题所在:我没有在GetExpression 中传递UseAutoExpandRules(默认为false)。现在我的代码按预期工作了!

感谢@Mia Wu-MSFT 将dte.Debugger.GetExpression("tempC", true, 1) 放入她的代码并让我发现了UseAutoExpandRules 参数

【讨论】:

以上是关于如何从 Debugger.GetExpression 获取 DisplayString 字段?的主要内容,如果未能解决你的问题,请参考以下文章

如何将数据从回收器适配器发送到片段 |如何从 recyclerview 适配器调用片段函数

如何从 Firebase 获取所有设备令牌?

如何直接从类调用从接口继承的方法?

如何从服务器获取和设置 android 中的 API(从服务器获取 int 值)?如何绑定和实现这个

如何从Mac从android studio中的fabric注销? [复制]

如何从设备中获取 PDF 文件以便能够从我的应用程序中上传?