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



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

有没有一种简单的方法可以从加载的 DLL 或 EXE 中获取说明、路径和版本信息?

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

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

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

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

给定您从组件类别管理器获得的对象的 CLSID,您将查找相应的二进制文件,如下所示:

  1. 打开注册表项HKEY_CLASSES_ROOTCLSID{xxxxxxxxx-yyyyy-zzzz-aaaa-bbbbbbbbbbbbbb },其中大括号内的字符串是要查找的对象的 CLSID。
  2. 如果这是一个进程内对象,则会有一个名为 InProcServer32 的子项,其"默认"REG_SZ包含所需 DLL 的完整路径。
  3. 如果这是一个进程外对象,则会有一个名为 LocalServer32 的子项,其"默认"REG_SZ包含所需 EXE 的完整路径。 在某些情况下,您可能需要修剪此字符串的命令行开关以仅获取 EXE 路径。
  4. 使用前面步骤中的 DLL 或 EXE,可以在 Win32 中调用 GetFileVersionInfo(),或者使用 System.Diagnostics.FileVersionInfo.GetVersionInfo 如果您有 .NET 可用)从可执行文件中检索版本信息结构,其中将包含版本和说明。

获取此信息的一种方法是简单地等待所有初始化完成,然后枚举加载的模块,将每个模块的详细信息转储到日志文件中。

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

最新更新