【问题标题】:Load 2 versions of the same DLL in the same process在同一个进程中加载​​同一个 DLL 的 2 个版本
【发布时间】:2011-06-28 10:46:58
【问题描述】:

我想完全按照here 的描述去做,但接受的解决方案对我不起作用。我想原因解释here

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

如果一个具有相同模块名称的 DLL 是 已经加载到内存中,系统 仅检查重定向和 在解决之前表现出来 加载的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>

这个问题有解决办法吗?

【问题讨论】:

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


    【解决方案1】:

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

    您有两种基本方法可以做到这一点,都涉及通过为其创建清单将“common”转换为私有 SxS 程序集。

    然后:

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

    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 已经包含它们自己的清单,系统将使用它们。如果没有,这将允许您为私有程序集指定搜索目录,而无需修改 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”程序集的版本匹配即可。

    【讨论】:

    • 谢谢。我将清单嵌入到 DLL 中。所以,看起来我做了你在 1 推荐的事情。或者我错过了什么?清单是否正确?
    • 我对方法1添加了一些说明。
    • 谢谢。我让它工作了。我不得不切换到 Windows7 并使用 SxsTrace 工具来查看发生了什么。设置好后就很容易了,但是如果没有这个工具,你就看不到哪里出了问题
    猜你喜欢
    • 1970-01-01
    • 2010-12-07
    • 1970-01-01
    • 2010-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-22
    • 1970-01-01
    相关资源
    最近更新 更多