【问题标题】:Can different versions of DLL be loaded in same application?可以在同一个应用程序中加载不同版本的 DLL 吗?
【发布时间】:2011-05-22 18:10:53
【问题描述】:

我的应用程序使用一个版本的库 (a.dll),我正在使用另一个 DLL(b.dll),而后者又使用我使用的同一库 (a.dll) 的旧版本。我正在通过嵌入清单文件来构建应用程序。我使用的 DLL 也使用嵌入式清单文件。我的 WinSXS 文件夹中有两个版本的库。我的应用程序无法加载适当版本的 DLL。

拥有一个单独的清单文件(不嵌入到 DLL 中)是否有助于解决问题?解决方法是什么?

【问题讨论】:

  • 使用 Dependency Walker 的分析功能来查看您的应用程序试图加载哪个 DLL。这可能已经为您指出了问题的原因。

标签: c++ dll manifest dllimport


【解决方案1】:

您的情况正是 WinSxS 应该解决的情况。它应该可以工作。

要么:清单文件指向相同的版本,要么清单文件之一未正确嵌入,要么

WinSxS 中的共享程序集安装了一个配置策略,该策略自动将 v1.0 的请求重定向到 v1.1


需要澄清一下:App.exe 和 b.dll 是否隐式链接到 a.dll?还是他们通过 LoadLibrary 加载它。

如果 B.DLL 使用 LoadLibrary 显式加载 A.DLL,那么您需要将 ISOLATION_AWARE_ENABLED 添加到您的预处理器定义中,以确保 B.DLL 进行的 LoadLibrary 调用在正确的激活上下文中查找。否则,它们将在由 EXE 的清单创建的默认激活上下文的上下文中生成。

【讨论】:

  • 我不确定 WinSxS 是否有帮助。 WinSxS 允许您为 exe 提供清单,以确保进程加载特定版本的 DLL。这里的问题是同一个进程中的不同模块需要同一个 DLL 的不同版本。 AFAIK WinSxS 没有为此提供解决方案,尽管我不是 WinSxS 方面的专家并且可能是错误的。
  • 嗯? App.exe,使用清单来引用 sharedassembly.1.1\a.dll,并加载 b.dll,其中还包含一个引用 sharedassembly.1.0\a.dll 的清单 - 这是 100% 的“应用程序隔离”场景旨在支持。
  • 这听起来像是“模块隔离”而不是“应用程序隔离”,但也许我错了。我对文档的快速检查给我的印象是 WinSxS 让 AppX.exe 加载 1.1\a.dll 和 AppB.exe 加载 1.0\a.dll,但不是一个应用程序加载同一个 DLL 的多个版本(这似乎是一个秘诀一般用于灾难,尽管它可以与某些 DLL 一起使用)。
  • @Christ,我很可能是错的。尽管文档远非明确,但我发现这似乎确实支持了您所说的话:@ 987654321@ - 所以+1 对我的回答。我也会在另一个问题中提到它,以防它在那里有用。
  • 该技术在一些地方完全被错误命名。应用程序隔离实际上意味着模块隔离,因为应用程序已经可以加载同一个 dll 的不同版本。 “应用程序隔离”和“应用程序清单文件”允许 dll 通过将进程划分为“激活上下文”来声明对同一(命名)dll 的依赖关系并加载不同版本的 dll。
【解决方案2】:

这取决于复制的 DLL 的功能以及它们的版本是否兼容。 (例如,它们是否都访问内存中的共享对象?如果是,那么很有可能会发生故障。)

这还取决于这两个同名 DLL 的加载方式。如果它不是具有完整路径的显式 LoadLibrary 之外的任何东西,那么事情可能无法正常工作。这里正在讨论这个问题:Determine the loaded path for DLLs

一般来说,如果幸运的话,它可能会起作用。如果可以的话,它可能会发生灾难性错误的事实是完全避免这个问题的一个很好的理由。 (在最坏的情况下,您可以将其中一个模块托管在另一个进程中并代理对它的所有调用。理想情况下,只需能够在两个模块中使用相同的 DLL 版本。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-28
    • 2010-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-30
    • 1970-01-01
    相关资源
    最近更新 更多