LoadLibrary() 无法加载带有清单和私有程序集的 DLL

发布于 2024-08-23 03:35:04 字数 1529 浏览 1 评论 0原文

我正在开发一个使用多个 DLL 的 Windows 应用程序 (EXE)。开发是在 VCExpress 2005 (VC 8.0) 中进行的,仅使用 C。

其中一些 DLL 是使用 LoadLibrary 根据EXE读取的配置文件。

重要的是:应用程序必须是可移植的(即无需安装即可从 USB 闪存驱动器或类似驱动器运行),并且插件 DLL 可能不与应用程序 EXE 位于同一文件夹中(遗留原因)。

对于 MSVC6,这很简单:编译、链接、分发 EXE 和 DLL。

对于 MSVC8,C 运行时库 (MSVCRT) 不再随操作系统一起分发,因此不能依赖它的安装。为了满足可移植性要求,我需要使用 私有程序集< /a>.所有 EXE 和 DLL 都已嵌入其清单。

我的问题:通过 LoadLibrary() 加载的插件 DLL 找不到 EXE 文件夹中的私有程序集,因此尝试加载它们会失败,除非 Microsoft.VC80.CRT 程序集安装在 winSxS 中。

问题:如果从插件 DLL 中删除清单,则一切正常。

我的问题

  1. 在问题案例中,Windows 似乎没有遵循程序集搜索序列动态链接库搜索顺序。具体来说,它在加载 DLL 的路径中查找私有程序集,而不是在加载应用程序 (EXE) 的路径中查找。
    我尝试通过将程序集放在 DLL 旁边并更改当前目录(以排除与工作目录相关的情况)来验证这一点,并获得预期的行为。其他人能否确认这是将 LoadLibrary 与 SxS 一起使用时的正常行为?

  2. 我是否正确地假设,如果没有清单,DLL 会回退到非 SxS 加载顺序,该顺序会查找 msvcr80.dll (而不是程序集清单 Microsoft.VC80.CRT .manifest)在 EXE 的文件夹中?

  3. 如果我对 (1) 和 (2) 的看法是正确的,那么仅从 DLL 中排除清单会损失什么?换句话说,为什么我不应该通过排除清单来解决我的问题?

I am working on a Windows application (EXE) that uses multiple DLLs. Development is in VCExpress 2005 (VC 8.0), using C only.

Some of these DLLs are plug-ins/add-ons/extensions that are dynamically loaded using LoadLibrary according to a configuration file read by the EXE.

Importantly: the application must be portable (in the sense of able to run from a USB flash drive or similar without installation), and the plug-in DLLs may not be in the same folder as the application EXE (legacy reasons).

With MSVC6 this is straightforward: compile, link, distribute EXE and DLLs.

With MSVC8 the C Runtime Library (MSVCRT) is no longer distributed with the OS, so one cannot rely on it being installed. To satisfy the portability requirement I need to use a private assembly. All EXEs and DLLs have had their manifests embedded.

My problem: the plug-in DLLs loaded via LoadLibrary() do not find the private assembly that is in the EXE's folder, so attempting to load them fails unless the Microsoft.VC80.CRT assembly is installed in winSxS.

The catch: if the manifests are removed from the plug-in DLLs, everything works.

My questions:

  1. In the problem case, Windows doesn't seem to be following either the Assembly searching sequence or the Dynamic link library search order. Specifically it is looking for the private assembly in the path from which the DLL was loaded, not from which the application (EXE) was loaded.
    I have attempted to verify this by putting the assembly adjacent to the DLL, and changing the current directory (to rule out related to working directory cases), and get the expected behaviour. Can anyone else confirm that this is the normal behaviour when using LoadLibrary with SxS?

  2. Am I right in assuming that without a manifest, the DLL falls back to non-SxS load order which is finding msvcr80.dll (rather than the assembly manifest Microsoft.VC80.CRT.manifest) in the EXE's folder?

  3. If I am right about (1) and (2), what do I lose by just excluding the manifest from the DLL? Rephrased, why shouldn't I solve my problem by just excluding the manifest?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

寂寞美少年 2024-08-30 03:35:04

您需要了解激活上下文是什么才能理解这个问题。

带有清单的 exe 或 dll 具有激活上下文 - 激活上下文是解析清单时发现的窗口类、依赖程序集、dll 和免注册 com 引用的列表。

没有清单的 exe 或 dll 使用进程默认激活上下文 - 如果 exe 具有激活上下文,则通常是 exe 的激活上下文。

在您的情况下,dll 有自己的激活上下文 - 因为它有一个清单。它始终是搜索程序集的清单文件(包含该文件/文件夹)的路径。

这就是为什么 Windows 启动时会在 dll 文件夹中搜索私有程序集。然后,当失败时,Windows 会在标准加载库搜索路径中搜索 dll:从 exe 的根文件夹开始。但它现在搜索 dll,而不是程序集 - 因此找不到包含 dll 的程序集文件夹。

  1. 没有。如果没有清单,DLL 将回退到使用默认激活上下文:exe 的清单。 此博客文章对此进行了一些解释。

  2. 排除清单。您失去的是让 dll 指定其自己的依赖程序集的能力。因此,您需要做的是将 dll 所需的任何依赖程序集添加到应用程序清单中。

You need to understand what an activation context is to understand this problem.

An exe, or dll, with a manifest, has an activation context - the activation context is a list of window classes, dependent assemblies, dlls, and registration free com references that were discovered when the manifest was parsed.

An exe, or dll, without a manifest, uses the process default activation context - which is usually the exe's activation context if the exe has an activation context.

In your case, the dll has its own activation context - because it has a manifest. And its always the path to the (file/folder that contains the) manifest file that is searched for assemblies.

Which is why windows starts by searching the dll's folder for the private assembly. Then, when that fails, Windows searches the standard load library search path for the dll: which starts with the exe's root folder. But its searching for dll's now, NOT assemblies - so the assembly folder containing the dll is not found.

  1. No. Without a manifest, the dll falls back to using the default activation context: the exe's manifest. This Blog Article explains it a bit.

  2. Exclude the manifest. What you loose is the ability to get the dll to specify its own dependent assemblies. What you need to do therefore, is add any dependent assemblies the dll needs, to the applications manifest.

世态炎凉 2024-08-30 03:35:04

与 CRT 静态链接。只要您的应用程序中不使用.Net(纯C/C++),它就可能与CRT 静态链接。

在我的应用程序中引入 .Net 迫使我从静态链接的 CRT 迁移到动态链接的 CRT。我还尝试找到一种在本地引用 CRT DLL 的方法,而无需显式安装它们,但我没有找到。因此,如果可能,请与 CRT 静态链接。

Link statically with the CRT. As long as you don't use .Net in your application (pure C/C++) it is possibly to statically link with the CRT.

The introduction of .Net in my application forced me to move from a statically linked CRT to a dynamically linked CRT. I also tried to find a way to refer to the CRT DLL's locally without the need to explicitly install them, but I didn't find it. Therefore, if possible, statically link with the CRT.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文