【问题标题】:Invoke a COM Method using InvokeMember使用 InvokeMember 调用 COM 方法
【发布时间】:2016-04-29 23:31:47
【问题描述】:

我正在包装一个 COM API 最终,我试图将更多代码推送到泛型中,而 api 中的继承模式没有帮助。

我有一个通用的 IBase, 有大约 80 个类代表结果集。它们非常相似,但它们都继承,或者说实现了非常基本的 IBase。

我已经尝试过扩展方法,但我不认为这是要走的路,因为 com 是后期绑定的,使用 Reflection.PropertyInfo 似乎是死路一条。

在泛型中,我们有子类型,所以我想我可以使用 InvokeMember 来调用我需要的方法/属性。

instnc = Activator.CreateComInstanceFrom(assy, tyepname)
retClass = Type.GetTypeFromProgID(progId)

我的挑战是找不到 progId。 我搜索了注册表,我做了很多猜测。 “Excel.Application”有效,所以基本方法是可靠的。

有问题的 com dll 是 Intuit Quickbooks api。 我尝试了很多变体

“QBFC13Lib.ICustomerRetList”

我在正确的轨道上吗?如果是这样,我在哪里可以找到 progId? 我应该尝试不同的策略吗?

从 oleView,我看到了 ICustomerRetList

[
  odl,
  uuid(DF331154-953C-4813-BAEC-F65DDBBFEB5B),
  helpstring("ICustomerTypeRetList Interface"),
  dual,
  oleautomation
]
interface ICustomerTypeRetList : IQBBase {
    [id(0x00000004), helpstring("method GetAt")]
    HRESULT GetAt(
                    long index, 
                    [out, retval] ICustomerTypeRet** retVal);
    [id(0x00000005), propget, helpstring("property Count")]
    HRESULT Count([out, retval] long* pVal);
    [id(0x00000006), helpstring("method Append")]
    HRESULT Append([out, retval] ICustomerTypeRet** retVal);
};

typeLib 中一些更相关的行

有 36 个接口声明。我认为我们已经确定我们不追求这些......我们想要实现这些的东西

interface ICustomerMsgRetList;    
interface ICustomerMod;

有许多行引用类型,例如下面的行。这些只是将客户作为属性的对象(例如采购订单)。这些都可以在接口声明中找到。自从我做 C++ 以来已经有一段时间了。 IQBBase 是指向指针的指针吗?大声思考,不需要答案。

HRESULT CustomerRef([out, retval] IQBBaseRef** pVal);    

所以是的,那里可能有一家工厂。我确实相信这些对象(ICustomerRetList 实现者)是可实例化的,它们显然是实例化的。但是 typelib 并没有放弃它的秘密。回到最初的问题,除非我能得到 progId,否则我认为没有答案。 progId 可能会被故意混淆。不知道。我知道我猜测他们并没有成功。据我所知,直觉支持论坛不再活跃。

【问题讨论】:

标签: vb.net reflection com system.reflection qbfc


【解决方案1】:

您写“有问题的 com dll 是 Intuit Quickbooks api”。我不太明白,因为那不是 DLL 的名称。如果您知道 DLL,您可以使用带有 DLL 名称的 Microsoft 实用程序 OleView,它会为您显示一个反编译的类型库,您可以在其中查看包括 ProgIds 在内的所有类型。

就个人而言,我会使用 regedit.exe,然后转到 HKEY_CLASSES_ROOT\TypeLib。从那里我会使用搜索工具搜索“Intuit”或“quickbooks”来定位类型库。如果找到类型库,则可以使用 OleView 浏览它。

如果您没有找到它,您可以查看您的 Quickbooks 安装,然后找到它的文件路径。找到路径后,进入RegEdit中的HKEY_CLASSES_ROOT,搜索路径。您应该找到一些具有路径的键,如果它们被标记为 LocalServer32 或 InProcServer32,这将为您提供 CLSID,您可以从 CLSID 中获取 ProgID

【讨论】:

  • 我发布了 ICustomerRetList 的输出。我看到一个 uuId 和一个帮助字符串。这些都是我所追求的吗?
  • 拥有接口名称对您没有帮助。您需要的是实现该接口的对象的名称。如果您的 PC 上有 Quickbooks,请转到其目录并查找类型库 (.tlb) 文件。它可能有一个,也可能没有。类型库可以嵌入在 DLL 或 EXE 中。您可以尝试在 Quickbooks 目录中的每个 DLL 或 EXE 上使用 OleView 来查找类型库。如果它公开了自动化方法,您最终会找到它。如果 Quickbooks DLL 是 64 位或 32 位也是 32 位,您需要做的另一件事是确保您的应用程序是 64 位。
  • 当我打开 OleViewer 时,File->Load TypeLib 并指向 qbfcLib13.dll... 我在左边看到一棵树,里面有枚举、接口和 dispInterfaces。我确实了解接口和实现接口的对象之间的区别。但是,我在文档中看到的只是对接口的引用。我不确定如何,但类名(如果有类名)似乎被屏蔽了。也许我没有找对地方。
  • 转到类型库的根目录,以便在右侧列出每个类型。它将采用 IDL 格式。全部选择并将其复制到记事本或某些编辑器中。然后搜索关键字“coclass”。实现具有该 MIDL 属性的对象将可通过 CoCreateInstance 创建。这些是您可以从代码或脚本创建的对象。他们还应该列出他们支持的默认接口。如果您查看那些 coclass 对象,它们将具有 uuid。您可以在注册表中搜索 UUID。当你找到它时,它应该有一个带有 ProgId 的键。
  • COM 中没有“构造函数”。可能发生的情况是您必须使用 QBSessionManager 来创建一个实现接口的对象,或者可能(大致)一个创建对象的对象......创建一个实现您的接口的对象。查找 ICustomerTypeList 的部分匹配项,例如“CustomerType”,甚至只是 Customer,然后尝试向后工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-03
  • 1970-01-01
  • 2020-06-05
相关资源
最近更新 更多