使用同一个DLL的多个版本
我遇到过这样一种情况:应用程序具有一个或多个 dll 的多个(不兼容)版本。
app.exe
a.dll // v3.0
...
plugins/foo/foo.dll
plugins/foo/a.dll // v4.0
plugins/foo/...
本例中app.exe依赖a.dllv3.0,foo.dll依赖a.dllv4.0。由于我的exe旁边的v3.0的搜索顺序LoadLibrarya.dll是先加载,然后因为已经在内存中,所以跳过后面的v4.0。
假设我不能:
- 重命名依赖的 dll(
a.dll在这种情况下) - 修改
app.exe或foo.dll将它们升级/降级到通用a.dll版本
有没有办法加载同名 dll 的多个版本来解决这个问题?我看到了有关 AppDomain 的这个答案,但那是针对托管 C# 应用程序的,我的用例是本机 C++ dll。
回答
您正在寻找的是一个Activation Context:
激活上下文是内存中的数据结构,其中包含系统可用于重定向应用程序以加载特定 DLL 版本、COM 对象实例或自定义窗口版本的信息。激活上下文的一部分可能包含 DLL 加载器使用的 DLL 重定向信息;另一部分可能包含 COM 服务器信息。激活上下文函数使用、创建、激活和停用激活上下文。激活函数可以将应用程序的绑定重定向到指定特定 DLL 版本、窗口类、COM 服务器、类型库和接口的版本命名对象。有关激活上下文函数和结构的更多信息,请参阅激活上下文参考。
app.exe可以在加载a.dllv3.0 时使用一个激活上下文,并在加载时使用另一个激活上下文,foo.dll因此它使用a.dllv4.0。
Raymond Chen 发布了一篇博客文章,如何指定我的 DLL 应该从 DLL 所在的同一目录解析 DLL 依赖项?,其中涵盖了与您非常相似的场景:
一位顾客有这样的加载两个DLL的程序,让我们给他们打电话
A.DLL和B.DLL。这两个 DLL 都使用一个名为C.DLL. 问题在于这两个 DLL 想要使用不同的不兼容版本的C.DLL. 这两个 DLLA.DLL和B.DLL驻留在不同的文件夹中,每个文件夹都有一个对应的C.DLL.
除了他的解决方案使用基于清单的方法使B.DLL系统隐式处理的激活上下文之外。如果您可以修改foo.dll以包含清单,则可以在您的情况下采用类似的方法。否则,您必须app.exe在加载之前手动创建一个新的激活上下文foo.dll。