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

运行时 COM 对象检查

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (4投票s)

2003年10月10日

3分钟阅读

viewsIcon

73381

downloadIcon

2223

如何检查运行时COM对象的内容。

引言

可能每个人都知道为对象创建监视器、检查其属性等等是多么令人愉悦。无论如何,你可能已经注意到VB在不同的会话之间会忘记你正在监视的内容,所以显而易见的想法是构建一个自定义的调试窗体来显示你需要的内容。但有一个问题,那就是你可以轻松地检查默认类型,但对于COM对象来说,情况完全不同。我的这个小而简单的控件解决了这个问题,因为它允许你通过一个TreeView控件来检查一个通用COM对象的全部运行时属性。

使用代码

用法非常简单

  • 创建一个窗体
  • 将一个ObjView控件添加到窗体上
  • 运行你的程序,
  • 运行时,你可以
    • 通过控件的Add方法添加一个对象进行检查。请注意,你需要提供一个字符串来唯一标识你的对象。
    • 使用Remove方法从检查中移除一个对象。
    • 通过Refresh方法刷新所有正在检查的对象的值。
    • 通过RefreshOBJ方法刷新单个对象,该方法需要第一个参数为对象的引用,第二个参数为你添加对象时给控件的标识符。

所有的检查工作都使用了TypeLib Information库(tlbinf32.dll),该库暴露了各种类和方法。请注意,VB COM对象不能暴露每个类超过一个接口(或者至少我没有找到任何这样做的对象),这个想法很简单:

  1. 获取给定对象的接口描述符
    Dim tliApp as TLI.TLIApplication
    Dim tliIrf as TLI.InterfaceInfo
            
    Set tliApp = new TLI.TLIApplication
    Set tliIrf = tliApp.InterfaceInfoFromObject(< object variable > )
  2. 检查tliIrf变量的Members集合,其中包含类暴露的所有公共成员
    Dim tliMI as TLI.MemberInfo For Each tliMi In tliIrf.Members ... Next

    每个MemberInfo类都包含指向选定接口的公共成员(函数、子程序、变量、属性……)的数据。相关的字段是:

    • Name:成员的名称,用于检索值。
    • Parameters:这是一个ParameterInfo集合,包含关于选定方法参数的信息。
    • InvokeKind:这是一个InvokeKinds枚举类型,用于说明这是哪种类型的成员。
    • ReturnType:这是一个VarTypeInfo类,包含关于返回类型的信息。
  3. 由于我想要创建一个类似调试器的对象,我做了以下假设:
    • 如果它是一个集合,或者一个实现了集合的对象,则分析每个项。要判断它是否为集合,控件使用以下过程:

      Private Function IsCollection(v As Variant) As Boolean
              Dim tlApp As TLI.TLIApplication
              Dim tlIrf As TLI.InterfaceInfo
              Dim tlmi As TLI.MemberInfo
              Dim Obj As Object
              
              If IsObject(v) Then
                      If TypeName(v) = "Collection" Then
                              IsCollection = True
              End If
              
                      Set Obj = v
                      Set tlApp = New TLI.TLIApplication
                      Set tlIrf = tlApp.InterfaceInfoFromObject(Obj)
              
                      For Each tlmi In tlIrf.Members
                              If LCase$(tlmi.Name) = "item" Then
                                      IsCollection = True
                                      Exit For
                              End If
                      Next
              End If
          
              Set tlmi = Nothing
              Set tlIrf = Nothing
              Set tlApp = Nothing
      End Function

      因此,如果对象没有Item方法,它就不会被识别为集合,这与VB的行为是一致的。

    • 如果不是集合,则使用以下表解析每个成员:

      • InvokeKind:如果不是GetINVOKE_PROPERTYGET),则丢弃。
      • 如果它有1个或更多参数,则丢弃。
      • 关于返回类型:
        • 它使用CallByName语句获取选定成员的当前值。
        • 如果它是一个对象,它将递归地遍历这个对象。
        • 如果不是,它将显示字符串成员名称 = 成员值

关注点

一个有趣的点是TypeInfo库如何管理枚举类型。它不将其视为long,而是将枚举类型的各项填充到ReturnType成员的TypeInfo.Members集合中,因此每一项都是一个TypeInfo,包含:

  • Value:枚举项的数值。
  • Name:与之关联的符号名称。

因此,使用For ... Each循环,很容易找到代表给定数值的符号名称,而这个数值通常开发者更容易理解。

历史

  • 2003/10/12:第一个版本公开发布。
© . All rights reserved.