65.9K
CodeProject 正在变化。 阅读更多。
Home

ComObject 可视化工具

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.77/5 (12投票s)

2010 年 4 月 20 日

CPOL

2分钟阅读

viewsIcon

27449

downloadIcon

582

Visual Studio 对象可视化工具,用于类型为 System.__ComObject 的对象

CodeSnippet

ComObject Visualizer

引言

最近我参与了一个处理 Excel 和 PowerPoint 应用程序的项目,遇到了在调试时无法查看 COM 对象类型的问题。我尝试使用 GetType,但它返回一个 __ComObject,而它本身不包含关于底层接口的任何有用的信息。

我决定为 Visual Studio 创建一个 可视化工具,它有助于在调试时处理 COM 对象。因此,本文将描述一种识别 COM 对象支持的接口的方法。

背景

以下是一个在 Excel 中查找形状并将其转换为 Office.FormsTextBox 控件的代码示例:

  using Microsoft.Office.Interop.Excel;
  using TextBox=Microsoft.Vbe.Interop.Forms.TextBox;

...

Shape shape = sheet.Shapes.Item("ctool");
OLEObject oleObject = (OLEObject) shape.OLEFormat.Object;
TextBox TextBox = (TextBox) oleObject.Object;

...

这段代码很简单,但我花了很多时间才找到一种方法。造成这种情况的原因有两个问题:

  • 在互联网上,他们建议以这种方式处理 Office.Forms 控件:
    Shape shape = sheet.Shapes.Item("ctool");
    TextBox TextBox = (TextBox) shape.OLEFormat.Object;

    尽管有建议,这段代码抛出了“无法转换”异常。

  • 仅使用基本工具,在 VS 中识别 COM 对象的底层类型并不容易。

Using the Code

类型识别的主要思想与 IUnknown 接口有关。所有 COM 对象都支持此接口,并且具有 QueryInterface 方法。要识别支持的接口,需要迭代所有当前加载的接口,并查询 COM 对象是否支持它。以下是执行此操作的 ComObjectSource 类的源代码。

  public class ComObjectSource : VisualizerObjectSource
  {
    public override void GetData(object target, Stream outgoingData)
    {
      Assembly[] assemblies = Thread.GetDomain().GetAssemblies();
      List<type> types = new List<type>();

      foreach (Assembly assembly in assemblies)
      {
        types.AddRange(
          FindInterfaceTypesForComObject(assembly, target));
      }

      new BinaryFormatter().Serialize(outgoingData, types);
    }

    public IEnumerable<type> FindInterfaceTypesForComObject
			(Assembly Assembly, object ComObject)
    {
      IntPtr iuknw = Marshal.GetIUnknownForObject(ComObject);

      foreach (Type type in Assembly.GetTypes())
      {
        Guid uid;

        if (!type.IsInterface ||
            (uid = type.GUID) == Guid.Empty)
        {
          continue;
        }

        IntPtr ipointer = IntPtr.Zero;
        Marshal.QueryInterface(iuknw, ref uid, out ipointer);

        if (ipointer != IntPtr.Zero)
        {
          yield return type;
        }
      }
    }
  }

要为 System.__ComObject 类型注册可视化工具,您需要添加以下内容:

[assembly: System.Diagnostics.DebuggerVisualizer(
typeof(Visualizer), 
typeof(ComObjectSource), 
TargetTypeName = "System.__ComObject, mscorlib, 
	Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", 
Description = "ComObject Visualizer")]

为了使用此可视化工具,您需要将 *.dll 文件放入 <Visual Studio 安装目录>\Common7\Packages\Debugger\Visualizers<我的文档目录>\Visual Studio 2005\Visualizers

关注点

我不再花更多时间来识别 COM 对象的类型。所以我也希望你也是如此。;-)

历史

  • [2008-02-21] - 文章的初始发布
© . All rights reserved.