我想完全按照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将通过
加载DLLLoadLibrary("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>
这个问题有解决方法吗?
答案 0 :(得分:6)
你在哪里嵌入清单? EXE还是DLL?
您有两种基本的方法,包括通过为其创建清单将“common”转换为私有SxS程序集。
然后:
如果DLL和DLL2包含列出依赖程序集的清单,则需要在其清单中添加dependentAssembly,将“acme.common”(例如)指定为依赖程序集。由于默认情况下始终在加载模块文件夹中搜索依赖程序集,因此每个DLL都将加载其自己的公共本地副本。
如果您只是依靠应用程序默认激活上下文来完成大部分繁重工作,那么您可以尝试使用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”程序集的版本匹配。