提问人:yanpengl 提问时间:5/26/2022 最后编辑:Eugene Astafievyanpengl 更新时间:5/26/2022 访问量:345
进程是否可以加载两个同名但版本不同的dll?
Is it possible for a process to load two dll with same name but different versions?
问:
两天前,我在 Microsoft 社区中发布了这个问题。我有一些好主意,做了一些实验,但还是失败了。为了获得更多帮助,我决定在这里发布这个问题。(原文:一个进程是否可以加载两个不同版本的dll?)
我开发了一个单词全包应用程序,它是一个可以通过单词加载的应用程序和一些与单词兼容的应用程序(在这个问题中,我称之为类单词应用程序,它们使用相同的ooxml标准)。我的加载项使用 CEF .net 绑定(反过来使用(chromium 嵌入框架))来呈现一些 Web 内容。下面是我的加载项项目中的一些详细信息。dll
cefglue
CEF
此加载项的平台目标是 ,由此类似单词的应用加载。启动时,我通过调用 来检查此加载项是在 32 位环境还是 64 位环境中加载的。之后,我为其他 chromium 库设置了适当的库路径,这取决于加载我的加载项 dll 的应用程序是 64 位还是 32 位。例如,在 64 位 word 中,我的加载项加载 64 位 .使用伪代码的一些细节:Any CPU
Environment.Is64BitProcess
libcef.dll
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中运行良好,但不幸的是,这在类似单词的应用程序中出现了一些问题。原因如下:
这个类似单词的应用程序也有自己的 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.dll
cefglue.dll
libcef.dll
libcef.dll
(->
代表 ,代表加载 dll 的独立可能路径)loads
|
我使用绝对路径加载,如果我先加载这个库,那个类似单词的应用程序不会加载它自己的(内置规则?),它计划使用我当时的崩溃,毕竟它需要版本 87。如果首先加载类似单词的应用程序,我的加载项将不会加载版本 67 ,则会出现异常。libcef.dll
libcef.dll
LoadLibraryEx
libcef.dll
libcef.dll
libcef.dll
version mismatch
总而言之,我需要的是将相同名称但版本不同的版本与类似单词的应用程序隔离开来,使其无法感知到我的加载项加载的相同名称的 dll。一些想法?谢谢。libcef.dll
答:
这是不可能实现的,因为 libcef.dll 在依赖项中还有其他 DLL,而您无法控制它们的加载。有关详细信息,请参阅动态链接库搜索顺序。该页面的重要部分是:
- 如果具有相同模块名称的 DLL 已加载到内存中,则系统在解析到加载的 DLL 之前仅检查重定向和清单,无论它位于哪个目录中。系统不搜索 DLL。
- 如果 DLL 具有依赖项,则系统将搜索依赖项 DLL,就好像它们仅使用其模块名称加载一样。即使通过指定完整路径加载了第一个 DLL,也是如此。
唯一可行的解决方案是使加载项严格依赖于另一个加载项版本,并使用具有完全相同版本的 CEF 框架生成加载项。如果另一个插件使用自定义构建的 CEF 框架,它可能不起作用。
评论
LoadLibrary
GetProcAddress
LoadLibrary
libcef.dll
libcef.dll
评论
LoadLibrary
LoadLibraryEx
my.dll
my.dll
libcef.dll
libcef.dll
chrome_elf.dll
my.dll
GetProcAddress
my.dll
libcef.dll