4

我在 Visual Studio 扩展包中的自定义工具窗口应该在 VS2012 和 VS2013 的调试会话期间评估自定义表达式。最终目标是建立一个图形化的观察窗口。因此,我必须从调试引擎中获取表达式结果的值。

评估通过

IDebugStackFrame2 -> IDebugExpressionContext2 -> ParseText 
IDebugExpression2 -> EvaluateSync -> IDebugProperty2

这里的第一个问题:在 Visual Studio 2013ParseText()上没有正确报错。但是IDebugProperty2检索到的是有效的(对于有效的表达式)。在 VS2012 上,我得到了无效表达式的正确错误。

这是真正的问题开始的地方。结果 Property2 表示一个复杂的自定义对象。为了将其可视化,需要检索其基类之一的特定属性。在我目前的尝试中,我使用IDebugProperty2.EnumChildren()它的成员一直走到类层次结构中的正确位置,类似于在 Visual Studio 的 Locals 窗口中所做的:

[result] -> base -> Raw -> base -> Non-public Members -> [private field] ... a.s.o.

这在某种程度上可行,但引入了以下问题:

问题1:获取某个复杂对象的内部成员

从 EnumChildren() 收到的成员及其顺序似乎取决于某些因素,这些因素对我来说并不明显: * 对象是否附加了调试可视化工具?(VS2013 忽略 EnumChildren 中的 enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_VALUE_RAW 并返回美化版本+“原始视图”节点,VS2012 按预期工作) * 是否显示“非公共成员”节点?有时是,有时不是 - 不知道它所依赖的 *“只是我的代码”的设置(?我在几篇文章中读到它,但无法真正找出可靠的规则) * ...必须有其他依赖项?

事实证明,这是获取某些复杂表达式结果对象的内部成员的一种非常老套的方法。有什么更好的方法?使用 IDebugProperty3 和一些 Debugger Visualizer 技巧?任何指针都会很棒。

问题2:VS2012给内存字节失败

一旦我拥有了结果对象的私有成员,我就会使用IDebugProperty2.GetMemoryBytes()它来“序列化”它的值(一个普通的 System.Array)并将其传输到我的自定义工具窗口。虽然这在 VS2013 中有效,但在 VS2012 中IDebugProperty2.GetMemoryBytes()总是返回 VS_Constants.S_FALSE。我真的没有想法。既然 VS2012 中有一个内存窗口,那么应该有什么方法可以让它在这里工作吗?我错过了什么?

用于查询内存 API 的代码:

IDebugMemoryContext2 memCtx = null;
IDebugMemoryBytes2 memBytes = null;

// getting the memory context is working ok
if (tmpProperty2.GetMemoryContext(out memCtx) == VSConstants.S_OK

  // VS2012 fails here, always returns S_FALSE, memBytes remains null:
  && (tmpProperty2.GetMemoryBytes(out memBytes) == VSConstants.S_OK)) { 
  ...

更多上下文:

OS: Windows 8 and 8.1 
Visual Studio: 2012 / 2013
Tool Window built with MPF (C#) in VS2013, (removed all vers. 12 references from the package before deploying to VS2012)
Debug engines: C# and Visual Basic
4

0 回答 0