c++ - 在同一个进程中加载​​同一个 DLL 的 2 个版本

标签 c++ visual-c++ windows-xp dll

我想完全按照描述的那样做here ,但公认的解决方案对我不起作用。我想原因已经解释过了here :

If a DLL with dependencies is loaded by specifying a full path, the system searches for the DLL's dependent DLLs as if they were loaded with just their module names.

If a DLL with the same module name is already loaded in memory, the system checks only for redirection and a manifest before resolving to the loaded DLL, no matter which directory it is in. The system does not search for the DLL.

我希望我的应用程序具有以下结构。

c:\Exe
 |
 |----- c:\DLL\DLL.dll, c:\DLL\common.dll 
 |
 |----- c:\DLL2\DLL2.dll, c:\DLL2\common.dll

我的 EXE 将通过以下方式加载 DLL

LoadLibrary("c:\\DLL\\DLL.dll");
LoadLibraryEx("c:\\DLL2\\DLL2.dll");

common 在这两种情况下都被隐式加载。

我尝试了 SetDllDirectory 选项,但始终只加载了一个 common.dll。

我在common.dll中添加了版本信息。 c:\DLL\common.dll 的版本为 2.0.1.0 而 c:\DLL2\DLL2.dll 的版本为 4.0.1.0

我用相应的版本信息嵌入了以下 list ,但没有帮助。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="common" version="4.0.1.0" processorArchitecture="x86"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
</assembly>

这个问题有解决办法吗?

最佳答案

你在哪里嵌入了 list ? EXE 还是 DLL?

执行此操作有两种基本方法,都涉及通过为其创建 list 将“公共(public)”变成私有(private) SxS 程序集。

然后:

  1. 如果 DLL 和 DLL2 包含列出依赖程序集的 list ,则您需要将 dependentAssembly 添加到它们的 list 中,并指定“acme.common”(例如)作为依赖程序集。由于始终会在加载模块文件夹中搜索依赖程序集,因此每个 DLL 都会加载其自己的本地通用拷贝。

  2. 如果您只是依靠应用程序的默认激活上下文来完成大部分繁重的工作,那么您可以尝试使用 ActivationContext API。 调用CreateActCtx两次,指定两个不同的文件夹作为结果上下文的基础文件夹。

在伪代码中:

HACTCTX h1 = CreateActCtx( ... for DLL ... );
HACTCTX h2 = CreateActCtx( ... for DLL2 ...);

ActivateActCtx(h1,...);
LoadLibrary("C:\\DLL\\DLL1.DLL");
DeactivateActCtx();
ActivateActCtx(h2,...);
LoadLibrary("C:\\DLL2\\DLL2.DLL");
DeactivateActCtx...

如果 dll 已经包含它们自己的 list ,系统将使用它们。如果没有,这将允许您为私有(private)程序集指定一个搜索目录,而无需修改 dll 本身。


要实现选项 1: 首先,我不建议尝试使用 dll 名称作为程序集名称。因此,在每个文件夹中创建如下所示的 list :

<!-- acme.common.manifest -->
<assembly manifestVersion="1.0">
    <assemblyIdentity type="Win32" name="acme.common" version="1.0.0.0" processorArchitecture="x86"/>
    <file name="common.dll"/>
</assembly>

您可以修改版本号以匹配每个文件夹中 common.dll 的版本,但这并不重要。

然后,要么是您列出的 list ,要么是这样的指令(如果您使用的是 Visual Studio)

#pragma comment(linker, "/manifestdependency:\"acme.common'"\
                   " processorArchitecture='*' version='1.0.0.0' type='win32'\"")

只需确保相关程序集版本与相应“acme.common”程序集的版本相匹配即可。

关于c++ - 在同一个进程中加载​​同一个 DLL 的 2 个版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5018355/

相关文章:

c++ - 确实应该关闭的文件共享违规

printing - 有什么方法可以拦截本地 Windows XP 机器上的打印作业吗?

c++ - 任何人都知道一些用于下载网页的小型图书馆?

c++ - 如何在函数内部操作 char 数组(字符串)的指针,它在 c/c++ 中作为参数传递

c++ - 接收 std::pair 作为参数并从花括号列表初始化中推导出类型的模板化函数

c++ - Visual Studio 2013 代码分析卡在 native 代码上

c++ - 在 Windows 中将数据与 SOCKET 相关联以用于 recv/WSARecv Hook 的最佳方法

c++ - glibc 在转换类型 C++ 后检测到 free() 无效的下一个大小(快速)

c++ - 如何将RapidXml添加到CMake项目?

python - WinXP 上的 boost.python "DLL load failed",VisualStudio 2005