代码之家  ›  专栏  ›  技术社区  ›  Roger Lipscombe

是否显示加载的COM对象的路径/版本信息?

com
  •  0
  • Roger Lipscombe  · 技术社区  · 16 年前

    我有一些代码使用组件类别管理器加载实现特定类别的所有类。

    有没有一种简单的方法从加载的dll或exe中获取描述、路径和版本信息?

    2 回复  |  直到 16 年前
        1
  •  1
  •   Tim Farley    16 年前

    当对象在同一单元的proc(即从dll)中加载时,您可能会使用一些技巧在内存中查找dll。例如,如果在虚拟方法表(vtable)中查找活动对象中的代码指针,它们通常会指向dll。然后,您可以使用一些系统调用来确定代码属于哪个加载的DLL。

    但有许多潜在的陷阱。如果必须将这些对象加载到单独的单元中,那么代码指针将指向存根,而不是实际的代码。此外,许多COM库实际上在运行时提供的包装类中实现了公共接口,因此在许多常见的用例中,这极有可能给您提供错误的信息。(即,您最终将获得运行时dll的信息,通常是MFC或ATL)。

    当一个对象在进程外加载(即从一个exe加载)时,我不知道任何合理的方法来追查哪个exe对应于活动对象。(显然,此数据必须存在于进程或COM运行时的某个位置,但它隐藏在存根的下面,并且可能取决于正在运行的Windows版本)。

    因此,除非您查看的是一组非常有限的对象(所有正在处理的对象都加载在与您相同的单元中),否则您最好的选择是使用注册表中的注册信息来查找所需的内容。这很麻烦,因为这是一个可以从操作系统的版本改变到版本的东西,但幸运的是,COM已经存在了足够长的时间,这些年来它并没有改变太多。

    给定从中获取的对象的clsid Component Categories Manager ,您将按如下方式查找相应的二进制文件:

    1. 打开注册表项 HKEY_CLASSES_ROOT\CLSID\{xxxxxxxxx-yyyyy-zzzz-aaaa-bbbbbbbbbbbbbb } 大括号内的字符串是要查找的对象的clsid。
    2. 如果这是一个进程内对象,将有一个名为 InProcServer32 谁的“默认” REG_SZ 包含所需的dll的完整路径。
    3. 如果这是一个进程外对象,将有一个名为 LocalServer32 谁的“默认” 雷格斯茨 包含所需的exe的完整路径。在某些情况下,您可能需要修剪命令行来关闭此字符串,以获取exe路径。
    4. 使用前面步骤中的dll或exe,可以调用 GetFileVersionInfo() 在Win32中(或使用 System.Diagnostics.FileVersionInfo.GetVersionInfo 如果有.NET可用),则从可执行文件中检索版本信息结构,该结构中将包含版本和说明。
        2
  •  0
  •   Roger Lipscombe    16 年前

    获取这些信息的一种方法,假设它仅用于日志记录目的,就是简单地等待所有初始化完成,然后枚举加载的模块,将每个模块的详细信息转储到日志文件中。

    显然,这只适用于inproc对象,如果应用程序非常动态,它将不起作用,但它也会捕获非COM DLL。