【问题标题】:How can I get TypeLibInfo from an ITypeLib pointer?如何从 ITypeLib 指针获取 TypeLibInfo?
【发布时间】:2021-04-11 06:14:03
【问题描述】:

我想使用 tlbinf32.dll 来读取 COM 对象的类型信息。目前我可以访问指向 ITypeLib 接口的指针。我可以使用 VTable 偏移量和 DispCallFunc 手动调用方法和导航,但是我希望使用该库的强大内置功能。

我在想,既然TLI.ClassInfoFromObject(Object As IUnknown) 可用于查询 IDispatch::GetTypeInfo 方法,我可以手动构造一个仅实现此方法的虚拟对象,以允许将 TypeInfo 读入内存。类似于manually defining IEnumVariant,其中大多数方法只返回E_NOTIMPL = &H80004001。这听起来可行吗?有没有更简单的方法可以使用 VBA 从指针访问 TypeInfo?


更新

需要明确的是,我的问题是我找不到声明 ITypeInfo 接口并允许我直接使用它的方法 - VBA 访问 IUnknownfrom stole2.tlb 所以我可以很好地使用它,但唯一的我可以在 mscorlib.dll 中找到声明的 ITypeInfo,但它是 doesn't have the COMVisible attribute,因此无法在 VBA、AFAIK 和 VBA 中访问它,并且 VBA 没有与 [ComImport] 等效的让您自己使用 GUID 定义它.所以我想使用 tlbinf32.dll 来避免我不得不使用原始指针。

【问题讨论】:

  • 这需要细节和/或清晰性。 ITypeLib(和相关的接口)是描述类型库的原始低级接口,而 tlbinf32 是原始接口之上的自动化兼容库(为 VB/VBA 创建),它们有点做同样的事情,但针对不同的类型的客户。我不明白你想做什么?
  • @SimonMourier 完全正确;我已经通过一些 COM 黑客访问了原始接口,这让我获得了比简单地调用 IDispatch::GetTypeInfo 更详细的版本(我认为,这是 tlbinf32 在后台从自动化对象实例中获取 typeinfo 的方法)。现在我有了原始接口,我想以某种方式将其读入 tlbinf32.dll 以获得更高程度的抽象。希望这是有道理的?
  • @SimonMourier 另见更新:) 澄清
  • 如果你有一个 ITypeLib 引用,那么这个类型库是从某个地方加载的。您应该能够获取此类型的库信息并从 tlbinf32 从头开始​​加载它
  • 如果您有 ITypeLib 引用,ITypeLib::GetLibAttr 应该为您提供类型库信息 (TLIBATTR) docs.microsoft.com/en-us/windows/win32/api/oaidl/…,您可以使用该信息通过 tlbinf32 从头开始​​加载它。

标签: vba com ole typelib tlbinf32


【解决方案1】:

原来 tlbinf32.dll 支持这个开箱即用但它是隐藏的。从帮助文件中:

ITypeLib As IUnknown
TypeLibInfoFromITypeLib(ByVal ptlib As IUnknown) As TypeLibInfo

在每个 TypeLibInfo 内部都是对 ITypeLib 实例的引用。在 事实上,TypeLibInfo 对象可以看作是对 比 ITypeLib 更容易编程的 ITypeLib 接口 本身。查看两个 TypeLibInfo 对象是否实际上引用相同的 内部对象,使用 VB 的 Is 运算符和 ITypeLib 属性 两个对象。 Is 运算符通常会返回 False TypeLibInfo 对象实际上对应于相同的底层 类型,但不适用于内部 ITypeLib 指针。 ITypeLib 属性是可设置的,因此您可以将 TypeLibInfo 对象放在 现有的 ITypeLib。

如果你有一个 ITypeLib 引用并且想要使用 TLI 对象,那么 你可以调用 TLI.TypeLibInfoFromITypeLib 来生成一个完整的 功能 TypeLibInfo 对象。

ITypeLib 属性和 TypeLibInfoFromITypeLib 方法是 被视为高级功能并被标记为隐藏。

强调我自己的

... ITypeInfo 指针的类似故事

那么如何使用呢?非常简单。首先是从指针中获取 IUnknown 的方法。例如:

Public Function ObjectFromObjPtr(ByVal Address As LongPtr) As IUnknown
    Dim result As IUnknown
    MemLongPtr(VarPtr(result)) = Address
    Set ObjectFromObjPtr = result
    MemLongPtr(VarPtr(result)) = 0
End Function

Private Property Let MemLongPtr(ByVal dest as LongPtr, ByVal value As LongPtr)
    CopyMemory ByVal dest, value, LenB(value)
End Property

接电话

Dim ITypeLibPtr As LongPtr
ITypeLibPtr = ... 'get the raw pointer

Dim ITypeLibObj As IUnknown
Set ITypeLibObj = ObjectFromObjPtr(ITypeLibPtr)

Dim NiceTypeLib As tli.TypeLibInfo
Set NiceTypeLib = tli.TypeLibInfoFrom(ITypeLibITypeLibObj)

或类似的词

【讨论】:

  • 我无法编辑单个字符。如果您进行其他编辑,请将tli.TypeLibInfoFromITypeLibITypeLibObj) 更改为tli.TypeLibInfoFromITypeLib(ITypeLibObj)。您是否正在尝试获取有关 VBA 类或外部库的信息?我问是因为我的印象是 VBA 在编译时使用的 ITypeLib 在运行时不可用。我可以通过 VBA 获得指向 ITypeInfo 接口的指针(参见 here),但是当我调用 ITypeInfo::GetContainingTypeLib 时,我得到一个空指针(HRESULT 为 S_OK)
  • @CristianBuse 感谢您的更正,我只是将所有内容直接输入答案而没有实际运行它:) 是的,我正在尝试检查 VBA 类,我的方法是模仿橡胶鸭子的方法用于支持其单元测试。 NGL 非常复杂,我花了很长时间才弄明白,但 this 是面包屑痕迹的开始......
  • 事实上here 是我当前的(WIP 错误)代码。基本上,VBE.References 对象有一个实例表(不是 vtable,上一层),可以让您导航一些高级运行时 TypeLib。要让 tlbinf32 在 64 位上工作,您需要遵循 this answer 中的说明,但是 tbh 破解 32 位 dll 以在 64 位环境中工作很可能是错误的来源,所以也许指针和 DispCallFunc 是解决问题的方法去...无论如何,这是一个好的开始,让您阅读一些信息
  • 不错。感谢分享。如果我能想到任何有用的东西,我会回顾并回复你。
猜你喜欢
  • 2021-01-07
  • 1970-01-01
  • 2020-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-01
  • 2013-12-30
  • 2018-06-14
相关资源
最近更新 更多