在同一过程中加载同一DLL的2个版本 [英] Load 2 versions of the same DLL in the same process

查看:143
本文介绍了在同一过程中加载同一DLL的2个版本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想完全按照此处所述进行操作,但是接受的解决方案对我不起作用。我想在此处中解释了原因:

I want to do exactly what it is described here, but the accepted solution does not work for me. I suppose the reason is explained here :


如果通过指定完整路径加载了具有依赖性的DLL
,则系统
搜索该DLL依赖的DLL
,就好像它们只加载了
模块名一样。

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.

如果具有相同模块名的DLL已经是
加载到内存中后,系统
仅检查重定向和
清单,然后再解析到
加载的DLL,无论它位于哪个目录
中。系统不会搜索
用于DLL。

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.

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

I wish to have my application in the following structure.

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

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

My EXE will load the DLLs through

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

在这两种情况下均会隐式加载。

common is implicitly loaded in both cases.

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

I tried the SetDllDirectory option, but there is always only one common.dll loaded.

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

I added version information in common.dll. c:\DLL\common.dll has version 2.0.1.0 while c:\DLL2\DLL2.dll has version 4.0.1.0

我嵌入了以下内容清单并显示相应的版本信息,但没有帮助。

I embedded the following manifest with the corresponding version info, but it did not help.

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

是否可以解决此问题?

推荐答案

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

Where have you embedded the manifest? The EXE or the DLLs?

您有两种基本方法,都可以通过为它创建清单将 common变成私有SxS程序集。

You have two basic ways of doing this, both involve turning "common" into a private SxS assembly by creating a manifest for it.

然后:


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

  1. If DLL and DLL2 contain manifests listing dependent assemblies, then you need to add a dependentAssembly to their manifests specifying "acme.common" (for example) as a dependent assembly. As dependent assemblies are always searched for, by default, in the loading modules folder, each DLL will load its own local copy of common.

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

If you are just relying on the applications default activation context to do most of the heavy lifting, then you can try using the ActivationContext API. Call CreateActCtx twice, specifying two the two different folders as the base folder for the resulting context.

使用伪代码:

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本身的情况下为私有程序集指定搜索目录。

If the dlls already contain their own manifests the system will use those. If not, this will let you specify a search directory for private assemblies without modifying the dll's themselves.

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

To implement Option 1: First, I don't recommend trying to use the dll name as the assembly name. So, create a manifest that looks like this in each folder:

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

You can fix the version number to match common.dll's version in each folder, but thats not important.

然后,列出清单或使用Visual Studio的类似指令

Then, either the manifest you list, or a directive like this if you are using Visual Studio

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

只要确保从属程序集版本与相应'acme的版本匹配即可。常见的程序集。

Just make sure the dependent assembly versions match the versions of the corresponding 'acme.common' assembly.

这篇关于在同一过程中加载同一DLL的2个版本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆