一个进程是否可以加载两个名称相同但版本不同的dll?

Is it possible for a process to load two dll with same name but different versions?

我 post 两天前在 Microsoft Community 中回答了这个问题。我想到了一些好主意并做了一些实验,但仍然失败了。如需更多帮助,我决定在此处 post 这个问题。 (原post:Is it possible for a process to load two dll with different versions?)

我开发了一个word all-in的应用,是一个dll可以word加载的应用和一些word兼容的应用(本题我称它为word-like app,他们用的是一样的ooxml 标准)。我的加载项使用 CEF .net 绑定 cefglue(它又使用 CEF(chromium 嵌入框架))来呈现一些 Web 内容。以下是我的加载项项目中的一些详细信息。

此加载项的平台目标是 Any CPU,由这个类似文字的应用程序加载。启动时,我通过调用 Environment.Is64BitProcess 检查此加载项是在 32 位环境还是 64 位环境中加载。之后,我为 libcef.dll 和其他 chromium 库设置了适当的库路径,这取决于加载我的加载项 dll 的应用程序是 64 位还是 32 位。例如,在 64 位字中,我的加载项加载 64 位 libcef.dll。使用伪代码的一些细节:

// Files in cef library folder
// locales/
// swiftshader/
// cef.pak
// cef_100_percent.pak
// cef_200_percent.pak
// cef_extensions.pak
// chrome_elf.dll
// d3dcompiler_47.dll
// devtools_resources.pak
// icudtl.dat
// libcef.dll
// libEGL.dll
// libGLESv2.dll
// ...

private _cefPath;
    
void FindLibraryPath() {
  bool is64BitEnv = Environment.Is64BitProcess;
  SetLibraryAndResourcePath(is64BitEnv); // set _cefPath and other path here
}
    
void InitializeCef() {
  // Load cef library
  // this method use LoadLibraryEx with the flag
  // LOAD_WITH_ALTERED_SEARCH_PATH to load libcef.dll
  CefRuntime.Load(_cefPath);
  // other statements for cef initialization
  ...
}

private void ThisAddIn_Startup(object sender, System.EventArgs e) {
  FindLibraryPath();
  InitializeCef();
}

这在 Microsoft Word 中运行良好,但不幸的是,这在类似 word 的应用程序中出现了一些问题。原因如下:
那个word-like app也有自己的cef库来加载它的网页内容(一些在线封面样式,页码样式等等,可以在当前文档中使用)。如果我在这个类文字应用程序中打开我的加载项,然后单击一些触发类文字应用程序加载其 Web 内容的按钮,这个类文字应用程序就会崩溃。为了分析原因,我应该给出一些事实:

加载我的插件的库

myaddin.dll(.net) -> cefglue.dll(.net) -> libcef.dll (native dll, version 67) -> other chromium native dll

图书馆类文字应用加载

|-> myaddin.dll(.net) -> cefglue.dll(.net) -> libcef.dll (native dll, version 67) -> other chromium native dll
|-> (加载自己的网页内容时) -> ... -> libcef.dll(native dll, version 87) -> other chromium native dll (in its installation目录)

(->代表loads,|代表加载dll的独立可能路径)

我使用绝对路径加载libcef.dll,如果我先加载这个库,那个类似word的应用程序不会加载它自己的libcef.dll([=29=的内置规则]?), 它计划使用我的 libcef.dll 然后崩溃,毕竟它需要版本 87。如果类文字应用程序首先加载 libcef.dll,我的加载项将不会加载版本 67 libcef.dll,然后我得到 version mismatch 异常。

总而言之,我需要的是将同名但不同版本 libcef.dll 与类似单词的应用程序隔离开来,使其无法感知我的加载项加载的同名 dll。一些想法?谢谢

这是不可能实现的,因为 libcef.dll 在依赖项中有其他 DLL,而您无法控制它们的加载。有关详细信息,请参阅 Dynamic-Link Library Search Order。该页面的重要部分是:

  • 如果具有相同模块名称的 DLL 已经加载到内存中,系统在解析为加载的 DLL 之前只检查重定向和清单,无论它在哪个目录中。系统不搜索动态链接库
  • 如果 DLL 具有依赖项,系统会搜索依赖的 DLL,就好像它们仅使用模块名称加载一样。即使第一个 DLL 是通过指定完整路径加载的,也是如此。

唯一可行的解​​决方案是让您的 add-in 严格依赖于另一个 add-in 版本,并使用具有完全相同版本的 CEF 框架来构建您的 add-in。如果另一个 plug-in 使用自定义构建的 CEF 框架,它可能无法工作。