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

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

提问人:yanpengl 提问时间:5/26/2022 最后编辑:Eugene Astafievyanpengl 更新时间:5/26/2022 访问量:345

问:

两天前,我在 Microsoft 社区中发布了这个问题。我有一些好主意,做了一些实验,但还是失败了。为了获得更多帮助,我决定在这里发布这个问题。(原文:一个进程是否可以加载两个不同版本的dll?)

我开发了一个单词全包应用程序,它是一个可以通过单词加载的应用程序和一些与单词兼容的应用程序(在这个问题中,我称之为类单词应用程序,它们使用相同的ooxml标准)。我的加载项使用 CEF .net 绑定(反过来使用(chromium 嵌入框架))来呈现一些 Web 内容。下面是我的加载项项目中的一些详细信息。dllcefglueCEF

此加载项的平台目标是 ,由此类似单词的应用加载。启动时,我通过调用 来检查此加载项是在 32 位环境还是 64 位环境中加载的。之后,我为其他 chromium 库设置了适当的库路径,这取决于加载我的加载项 dll 的应用程序是 64 位还是 32 位。例如,在 64 位 word 中,我的加载项加载 64 位 .使用伪代码的一些细节:Any CPUEnvironment.Is64BitProcesslibcef.dlllibcef.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中运行良好,但不幸的是,这在类似单词的应用程序中出现了一些问题。原因如下:
这个类似单词的应用程序也有自己的 cef 库来加载其 Web 内容(一些在线封面样式、页码样式等,这些样式已准备好在当前文档中使用)。如果我在这个类似单词的应用程序中打开我的加载项,然后单击一些按钮来触发类似单词的应用程序加载其 Web 内容,则这个类似单词的应用程序会崩溃。为了分析原因,我应该给出一些事实:

我的插件加载的库

myaddin.dll(.net)-> cefglue.dll(.net) ->(本机 DLL,版本 67) ->其他 Chromium 本机 DLLlibcef.dll

库 Word 类应用程序加载

|-> (.net) -> (.net) ->(本机 DLL,版本 67)->其他 Chromium 本机 DLL |->(加载自己的 Web 内容时) -> ... ->(本 DLL,版本 87) ->其他 Chromium 本机 DLL
(在其安装目录中)
myaddin.dllcefglue.dlllibcef.dlllibcef.dll

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

我使用绝对路径加载,如果我先加载这个库,那个类似单词的应用程序不会加载它自己的(内置规则?),它计划使用我当时的崩溃,毕竟它需要版本 87。如果首先加载类似单词的应用程序,我的加载项将不会加载版本 67 ,则会出现异常。libcef.dlllibcef.dllLoadLibraryExlibcef.dlllibcef.dlllibcef.dllversion mismatch

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

C# .NET Chromium Chromium 嵌入式 Cefglue

评论

0赞 Eugene Astafiev 5/26/2022
我想这个问题与 Word 加载项无关,因此该问题与在基于 .net 的应用程序中使用 chromium 有关,对吗?
0赞 yanpengl 5/26/2022
@EugeneAstafiev是的。事实上,它与Word加载项无关。只是一个问题如何在一个进程中加载两个不同版本的dll。
0赞 yanpengl 5/26/2022
@EugeneAstafiev 一开始,我不知道为什么会出现这个错误,现在我可以理解为什么了。在犯了很多错误之后,我现在构思了一个解决方案(做一个实验,还没有完成整个代码),使用(不)加载,在加载中(如果我正确理解加载顺序,将加载其他dll)。在我用于搜索 cef 函数中,这些函数又用于我的加载项中。 是我的加载项和 之间的抽象层。LoadLibraryLoadLibraryExmy.dllmy.dlllibcef.dlllibcef.dllchrome_elf.dllmy.dllGetProcAddressmy.dlllibcef.dll

答:

3赞 273K 5/26/2022 #1

这是不可能实现的,因为 libcef.dll 在依赖项中还有其他 DLL,而您无法控制它们的加载。有关详细信息,请参阅动态链接库搜索顺序。该页面的重要部分是:

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

唯一可行的解决方案是使加载项严格依赖于另一个加载项版本,并使用具有完全相同版本的 CEF 框架生成加载项。如果另一个插件使用自定义构建的 CEF 框架,它可能不起作用。

评论

0赞 yanpengl 5/26/2022
你的话给我的期望泼了一盆冷水:)
0赞 yanpengl 5/26/2022
我想我可以用它来定位函数。虽然我在加载库之前设置了不同的当前目录,但两次返回的句柄是相等的。:(LoadLibraryGetProcAddressLoadLibrary
0赞 273K 5/26/2022
这是链接页面上描述的确切行为,如果您尚未重命名 libcef.dll。如果重命名它,进一步加载其他 CEF 库将返回相等的句柄。
0赞 yanpengl 5/26/2022
感谢您指出,我无法再次构建由类似单词的应用程序安装的程序,否则它会使我的程序变得脆弱。谁知道这个类似单词的应用程序明天是否会改变自己。我必须转向 webview2。libcef.dlllibcef.dll
0赞 273K 5/26/2022
在加载项启动时,您可以检查加载的 cef 模块的 md5/sha1,以确保它是正式的并继续正常运行。如果校验和不同,则显示有关与第三个加载项不兼容的错误。