0

这个程序的 stdafx.h 有点像下面这样。

// ...
#import "./lib/64/msado15.dll" rename("EOF", "EndOfFile") no_namespace
// ...

该程序运行良好,没有任何问题。

我很好奇如果我删除 msado15.dll 会发生什么。所以,我删除了它,程序仍然可以正常工作。

我认为为什么程序在同一目录中没有 msado15.dll 的情况下工作的原因一定是 dll 文件加载到了其他地方。

为了确定 dll 的确切加载位置,我使用了“Dependancy Walker”,我发现这个程序根本没有加载 msado15.dll。

如果我能弄清楚我错过了什么,我会很高兴。

提前致谢。

4

1 回答 1

3

Dependency Walker只能查看静态 DLL 依赖项(在 EXE 的导入表中有引用)。如果在运行时通过LoadLibrary(或通过延迟加载——使用/delayload)加载 DLL,Dependency Walker将无法看到这一点。

#import实际上并没有对 DLL 施加静态依赖。它在编译时从 DLL 加载 COM 类型库信息。这被转换为类型库中定义的 COM 类和接口的 C++ 绑定。您可以在or目录.tli中看到这些.tlh文件。您可能能够删除 DLL 文件,并且——只要这些文件仍然存在——VS 可能会继续成功构建您的项目。DebugRelease

同样,在运行时,由于#import实际上并未对 DLL 施加静态依赖(即:它不会将其添加到 EXE 中的导入表中),因此Dependency Walker将无法看到此依赖。

但是,在运行时,EXE 将调用(间接)LoadLibrary,并且(如果缺少 DLL)这将导致运行时失败,您的程序可能会正确处理,或者可能导致程序崩溃。

即使说了这么多,也#import只是导入了一个 COM 类型库。COM 类型库定义了 COM 对象中使用的接口以及CLSID这些对象的值。为了找到实现 COM 对象的代码,CLSID使用注册表解析值(在HKEY_CLASSES_ROOT\CLSID. 中。实现 COM 对象的代码实际上可能与原始类型库不在同一个二进制文件中

这意味着在运行时甚至可能不需要 DLL。然而,我认为这种情况很少见。

此外,COM 对象可以实现为进程外对象(意味着加载了另一个 EXE)。在这种情况下,加载到您的进程中的所有内容都是为相关接口配置的代理/存根 DLL。通常,这些将使用 TLB 定义(在这种情况下,您的#import-ed DLL 将被加载);但它们可能在完全不同的 DLL 中实现。无论哪种方式,DLL 都将被动态加载,这意味着Dependency Walker不会看到它。

要查看进程加载了哪些 DLL,您将需要 SysInternals Process MonitorProcess Explorer之类的东西。

于 2012-08-16T08:01:55.697 回答