我有一些代码使用组件类别管理器来加载所有实现特定类别的类。
有没有一种简单的方法可以从加载的 DLL 或 EXE 中获取描述、路径和版本信息?
当对象在同一个单元中以进程内(即从 DLL)加载时,您可能会采取一些技巧来在内存中找到 DLL。例如,如果您在虚拟方法表 (vtable) 中查找指向活动对象的代码指针,它们通常会指向 DLL。然后,您可以使用一些系统调用来确定该代码属于哪个加载的 DLL。
但是有很多潜在的陷阱。如果您必须将这些对象加载到单独的单元中,则代码指针将指向存根而不是实际代码。此外,许多 COM 库实际上在运行时提供的包装类中实现了公共接口,因此这很可能在许多常见用例中为您提供错误信息。(即,您最终会获得运行时 DLL 的信息,通常是 MFC 或 ATL)。
当一个对象被加载到进程外(即从一个 EXE 中)时,我不知道有任何合理的方法来追踪哪个 EXE 对应于活动对象。(显然,这些数据必须存在于您的进程或 COM 运行时中的某个位置,但它隐藏在存根下方的某个位置,并且可能取决于您正在运行的 Windows 版本)。
因此,除非您正在查看一组非常有限的对象(所有与您在同一个单元中加载的进程内),否则您最好的选择可能是使用注册表中的注册信息来查找您需要的内容。这很麻烦,因为这是可以从操作系统版本到版本之间变化的事情之一,但幸运的是,COM 已经存在了足够长的时间,以至于这些年来这并没有发生太大的变化。
给定您从Component Categories Manager获得的对象的 CLSID ,您将查找相应的二进制文件,如下所示:
HKEY_CLASSES_ROOT\CLSID\{xxxxxxxxx-yyyyy-zzzz-aaaa-bbbbbbbbbbbbbb
},其中大括号内的字符串是您要查找的对象的 CLSID。REG_SZ
包含您需要的 DLL 的完整路径。REG_SZ
包含您需要的 EXE 的完整路径。在某些情况下,您可能必须修剪命令行开关关闭此字符串以仅获取 EXE 路径。假设它仅用于记录目的,获取此信息的一种方法是简单地等待所有初始化完成,然后枚举加载的模块,将每个模块的详细信息转储到日志文件中。
显然,这只适用于 inproc 对象,如果应用程序非常动态,它就不起作用,但它也会捕获非 COM DLL。