LoadLibrary()无法加载包含清单和专用程序集的DLL

LoadLibrary()无法加载包含清单和专用程序集的DLL,dll,manifest,msvcrt,loadlibrary,Dll,Manifest,Msvcrt,Loadlibrary,我正在使用多个DLL的Windows应用程序(EXE)上工作。开发是在VCExpress 2005(VC8.0)中进行的,仅使用C 其中一些DLL是插件/加载项/扩展,根据EXE读取的配置文件使用动态加载 重要提示:应用程序必须是可移植的(在某种意义上说,无需安装即可从USB闪存驱动器或类似设备运行),并且插件DLL可能与应用程序EXE不在同一文件夹中(遗留原因) 对于MSVC6,这很简单:编译、链接、分发EXE和DLL 对于MSVC8,C运行时库(MSVCRT)不再随操作系统一起分发,因此不能

我正在使用多个DLL的Windows应用程序(EXE)上工作。开发是在VCExpress 2005(VC8.0)中进行的,仅使用C

其中一些DLL是插件/加载项/扩展,根据EXE读取的配置文件使用动态加载

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

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

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

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

陷阱:如果从插件DLL中删除清单,则一切正常

我的问题

  • 在出现问题的情况下,Windows似乎没有遵循或。具体来说,它是在加载DLL的路径中查找专用程序集,而不是在加载应用程序(EXE)的路径中查找专用程序集。
    我试图通过将程序集放在DLL旁边并更改当前目录(以排除与工作目录相关的情况)来验证这一点,并获得预期的行为。其他人是否可以确认这是SxS使用
    LoadLibrary
    时的正常行为

  • 如果没有清单,DLL会返回到EXE文件夹中查找
    msvcr80.DLL
    (而不是程序集清单
    Microsoft.VC80.CRT.manifest
    )的非SxS加载顺序,这一假设正确吗

  • 如果我对(1)和(2)的看法是正确的,那么仅仅从DLL中排除清单会有什么损失?换言之,为什么我不能通过排除清单来解决我的问题


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


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

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

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

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

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

    这就是为什么windows首先搜索dll文件夹中的专用程序集。然后,当该操作失败时,Windows将在标准加载库搜索路径中搜索dll:该dll以exe的根文件夹开始。但它现在搜索的是dll,而不是程序集,因此找不到包含dll的程序集文件夹

  • 不可以。如果没有清单,dll会退回到使用默认激活上下文:exe的清单。解释一下

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


  • 谢谢-我看到了这一点,并讨论了静态链接与动态链接的相对优点。我对使用静态链接犹豫不决,因为我不确定API是否允许/期望在不同的模块中发生资源分配和释放,这将导致应用程序崩溃。静态链接也会导致二进制文件膨胀。需要添加一点-当嵌入清单包含publicKeyToken引用时,加载程序似乎会忽略应用程序本地目录。如果有足够的信息,加载程序总是首先在WinSxS中查找。但是,即使有publicKeyToken,它也会返回到本地。