【问题标题】:Using multiple versions of same DLL使用同一个 DLL 的多个版本
【发布时间】:2021-03-29 06:21:48
【问题描述】:

我遇到过这样一种情况,即应用程序具有一个或多个 dll 的多个(不兼容)版本。

app.exe
a.dll                // v3.0
...
plugins/foo/foo.dll
plugins/foo/a.dll    // v4.0
plugins/foo/...

在此示例中,app.exe 依赖于 a.dll v3.0,foo.dll 依赖于 a.dll v4.0。由于我的 exe 旁边的search order of LoadLibrary a.dll v3.0 先加载,然后由于它已经在内存中,所以跳过后面的 v4.0。

假设我不能:

  • 重命名依赖的dll(本例中为a.dll
  • 修改app.exefoo.dll 以将它们升级/降级为通用a.dll 版本

有没有办法加载同名 dll 的多个版本来解决这个问题?我看到了关于 AppDomain 的 this answer,但那是针对托管 C# 应用程序的,我的用例是本机 C++ dll。

【问题讨论】:

  • 这里当然标明了DLL名称中包含版本号,请楼主帮忙。否则,您将不得不与an assembly manifest 争吵。
  • 感谢@HansPassant 在那里搜索现在让我陷入了Isolated Applications and Side-by-side Assemblies 的兔子洞,乍一看听起来很有希望。我会做一些挖掘,看看是否可以解决这个用例。
  • 另一个兔子洞是延迟加载的库和通知挂钩 (example)。但必须能够修改一些东西。

标签: c++ windows dll


【解决方案1】:

您正在寻找的是Activation Context

Activation contexts 是内存中的数据结构,包含系统可用于重定向应用程序以加载特定 DLL 版本、COM 对象实例或自定义窗口版本的信息。激活上下文的一部分可能包含 DLL 加载程序使用的 DLL 重定向信息;另一部分可能包含 COM 服务器信息。激活上下文函数使用、创建、激活和停用激活上下文。激活函数可以将应用程序的绑定重定向到指定特定 DLL 版本、窗口类、COM 服务器、类型库和接口的版本命名对象。有关激活上下文函数和结构的更多信息,请参阅Activation Context Reference

app.exe 在加载a.dll v3.0 时可以使用一个激活上下文,并在加载foo.dll 时使用另一个激活上下文,因此它使用a.dll v4.0。

Raymond Chen 发表了一篇博客文章,How can I specify that my DLL should resolve a DLL dependency from the same directory that the DLL is in?,其中涵盖了与您的情况非常相似的场景:

一个客户的程序加载了两个 DLL,我们称它们为 A.DLLB.DLL。这两个 DLL 都使用一个名为 C.DLL 的通用帮助 DLL。问题是这两个 DLL 想要使用C.DLL不同的不兼容版本A.DLLB.DLL 这两个 DLL 位于不同的文件夹中,每个文件夹都有一个对应的 C.DLL 副本。

除了他的解决方案使用基于清单的方法使B.DLL 的激活上下文由系统隐式处理。如果您可以修改 foo.dll 以包含清单,则可以在您的情况下采用类似的方法。否则,您必须在加载foo.dll 之前手动让app.exe 创建一个新的激活上下文。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-18
    • 1970-01-01
    • 1970-01-01
    • 2016-12-08
    • 1970-01-01
    • 2011-06-28
    相关资源
    最近更新 更多