启用本机代码调试以深入了解COM对象。

14

我有一些使用由COM公开的第三方库(ArcObjects)的代码。例如,有IGeometry接口。

IGeometry geometry = GetGeometry();

现在当我想查看对象成员时,我会打开QuickWatch:

enter image description here

我读了几篇文章,都指向了Visual Studio 2015中的“启用本机代码调试”选项。我已经启用了该选项,但没有效果。

如何让调试器公开COM对象的成员?

编辑:在使用VS2010和.NET 3.5时,可以这样做:

enter image description here


也许这就是你要找的答案:https://learn.microsoft.com/zh-cn/visualstudio/debugger/how-to-debug-in-mixed-mode - rak007
你的 DLL 文件是否有关联的 pdb 文件? - rak007
@rak007 不,实际上我不想调试代码,只是查看其(公共)接口。据我所知,这应该可以在不使用pdb的情况下完成。 - MakePeaceGreatAgain
调试器引擎在检查COM接口方面的能力受到限制,本地调试并不能改变这一点。您可以尝试从“动态视图”中获取信息,它会尝试使用IDispatch成员来获取类型信息。但是如果IDispatch.GetTypeInfo()返回null,则无法实现该操作。请尝试使用geometry.IsEmpty确保管道正常。在gis.stackexchange.com网站上找到此产品的其他用户。 - Hans Passant
@HansPassant 这真的很烦人。我以为这不是 ArcGIS 特有的问题,所以在这里发布了这个问题,而不是在 GIS 上发布。 "动态视图" 也没有帮助,无论如何还是谢谢。 - MakePeaceGreatAgain
显示剩余2条评论
2个回答

9
启用未托管调试只有在您同时拥有组件的PDB和源代码时才能产生有用的副作用。然而,这些类型的组件供应商不会披露这些内容。您之所以能看到任何东西,仅因为您让VS为COM组件生成了Interop程序集。该程序集将组件类型库中的声明转换为等效的.NET类型,例如IGeometry,其实在底层可能是一个C++类。
这就是顶部视图和底部截图之间的重大区别。从VS2010和.NET 4.0开始,不再需要此Interop程序集。一般来说,"类型嵌入"是一个非常有用的功能,它可以避免部署组件的PIA。对于Office互操作尤其重要。
类型嵌入会积极地删除源代码中未使用的类型和成员。剩下的被嵌入到最终程序集中,从而消除了部署Interop程序集或PIA的需要。换句话说,您无法在调试器中看到IGeometry.Envelope,因为您的源代码没有使用该属性。这是由类型嵌入机制删除的。
解决方法很简单。选择项目的引用节点中的COM引用,并将其"嵌入Interop类型"属性设置为False。测试后可以保留此设置,但不要忘记部署Interop程序集。

类型嵌入将所有包装本机类型为适当的.NET类型的互操作类型放入调用程序集中,但省略在该调用程序集中未使用的所有成员。因此,如果我在代码的某个地方使用 IGeometry.SomeMember,则可以在调试器中看到其值,但是对于 IGeometry.Envelope,由于它实际上未在我的代码中使用,因此不会看到其值。 - MakePeaceGreatAgain
1
“Embed Interop Types” 在我们的环境中已经设置为 false。我们还依赖于 ArcObjects 组件在我们的环境中,这些组件似乎作为主要互操作组件 (PIA) 运行。然而,即使使用这些组件,我们仍无法从对象中获取更有意义的信息。 - MakePeaceGreatAgain

5

根据评论建议,我在 gis.stackexchange.com 上发布了这个问题,并从中引用我们的解决方案:

在 Visual Studio 中,转到 工具-->选项-->调试,启用"使用托管兼容模式"选项。


这在我的Visual Studio 2019中有效 - 而上面描述的“嵌入互操作类型”选项没有任何效果。不过,你有什么想法为什么会有效呢? - Dai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接