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

时间:2011-02-16 15:29:30

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

我想完全按照here的描述进行操作,但接受的解决方案对我不起作用。我想原因是here

  

如果加载了具有依赖项的DLL   通过指定完整路径,系统   搜索DLL的相关DLL   好像他们只是满载他们的   模块名称。

     

如果具有相同模块名称的DLL是   已装入内存的系统   仅检查重定向和a   在解决之前表现出来   加载DLL,无论哪个目录   它在。系统不搜索   对于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

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

<?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>

这个问题有解决方法吗?

1 个答案:

答案 0 :(得分:6)

你在哪里嵌入清单? EXE还是DLL?

您有两种基本的方法,包括通过为其创建清单将“common”转换为私有SxS程序集。

然后:

  1. 如果DLL和DLL2包含列出依赖程序集的清单,则需要在其清单中添加dependentAssembly,将“acme.common”(例如)指定为依赖程序集。由于默认情况下始终在加载模块文件夹中搜索依赖程序集,因此每个DLL都将加载其自己的公共本地副本。

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

  3. 在伪代码中:

    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已包含自己的清单,系统将使用这些清单。如果没有,这将允许您指定私有程序集的搜索目录,而无需修改dll本身。


    实施选项1: 首先,我不建议尝试使用dll名称作为程序集名称。因此,在每个文件夹中创建一个类似于此的清单:

    <!-- 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版本,但这并不重要。

    然后,如果您使用的是Visual Studio

    ,请列出清单,或者使用此类指令
    #pragma comment(linker, "/manifestdependency:\"acme.common'"\
                       " processorArchitecture='*' version='1.0.0.0' type='win32'\"")
    

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