我在Visual Studio Extension包中的自定义工具窗口应该在VS2012和VS2013的调试会话期间评估自定义表达式。最终目标是构建图形监视窗口。因此,我必须从调试引擎中获取表达式结果的值。
评估通过
正常运行IDebugStackFrame2 -> IDebugExpressionContext2 -> ParseText
IDebugExpression2 -> EvaluateSync -> IDebugProperty2
此处的第一个问题:在Visual Studio 2013上ParseText()
无法正确报告错误。但是检索到的IDebugProperty2
是有效的(对于有效的表达式)。在VS2012上,我得到了无效表达式的正确错误。
这是真正的问题开始的地方。结果Property2表示复杂的自定义对象。为了使其可视化,需要检索来自其中一个 base 类的特定属性。在我目前的尝试中,我使用IDebugProperty2.EnumChildren()
将其成员移动到类层次结构中的正确位置,类似于在Visual Studio中的Locals窗口中执行的操作:
[result] -> base -> Raw -> base -> Non-public Members -> [private field] ... a.s.o.
这在某种程度上有效但引入了以下问题:
从EnumChildren()收到的成员及其订单似乎取决于一些对我来说不明显的因素: *对象是否附加了Debug Visualizer? (VS2013忽略EnumChildren中的enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_VALUE_RAW并返回美化版本+“Raw View”节点,VS2012按预期工作) *是否显示“非公开会员”节点?有时候,它有时并不是 - 它不依赖于它所依赖的东西 *设置'只是我的代码'(?我在几个帖子中读到它但无法确定可靠的规则) * ...必须有其他依赖项?
这被证明是一种真正 hacky方式来获取某个复杂表达式结果对象的内部成员。什么是更好的方法?使用IDebugProperty3和一些Debugger Visualizer技巧?任何指针都会很棒。
一旦我拥有结果对象的私有成员,我使用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