【问题标题】:LoadLibrary() fails to load DLL with manifest and private assemblyLoadLibrary() 无法使用清单和私有程序集加载 DLL
【发布时间】:2011-01-21 02:02:15
【问题描述】:

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

其中一些 DLL 是插件/附加组件/扩展,它们根据 EXE 读取的配置文件使用 LoadLibrary 动态加载。

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

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

使用 MSVC8,C 运行时库 (MSVCRT) 不再随操作系统一起分发,因此人们不能依赖它的安装。为了满足可移植性要求,我需要使用private assembly。所有的 EXE 和 DLL 都嵌入了它们的清单。

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

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

我的问题

  1. 在问题的情况下,Windows 似乎没有遵循Assembly searching sequenceDynamic link library search order。具体来说,它在加载 DLL 的路径中查找私有程序集,而不是从加载应用程序 (EXE) 的路径中。
    我试图通过将程序集与 DLL 相邻并更改当前目录(以排除与工作目录相关的情况)来验证这一点,并获得预期的行为。其他人可以确认这是将LoadLibrary 与 SxS 一起使用时的正常行为吗?

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

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

【问题讨论】:

    标签: dll manifest msvcrt loadlibrary


    【解决方案1】:

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

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

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

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

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

    1. 没有。如果没有清单,dll 将回退到使用默认激活上下文:exe 的清单。 This Blog Article 稍微解释一下。

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

    【讨论】:

    • 补充一点 - 当嵌入式清单包含 publicKeyToken 引用时,加载器似乎忽略了应用程序本地目录。
    • 加载程序总是如果有足够的信息,首先会在 WinSxS 中查找。但是,即使有 publicKeyToken,它也会退回到本地。
    【解决方案2】:

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

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

    【讨论】:

    • 谢谢 - 我看到 stackoverflow.com/questions/238465stackoverflow.com/questions/787216 还讨论了静态与动态链接的相对优点。我对使用静态链接犹豫不决,因为我不确定 API 是否允许/期望资源分配和释放在不同的模块中发生,这会使应用程序崩溃。静态链接也会导致二进制文件膨胀。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多