在程序启动时从另一个目录加载一个DLL

我的基本问题是:我的程序(MyProgram.exe)有一个来自另一个程序(OtherProgram)的DLL的依赖,我试图避免每次更新OtherProgram时重新打包一个新的DLL。 我想在启动时在OtherProgram的DLL中有MyProgram.exe链接,但是我不完全确定Windows允许这样做。 所以如果有某种解决方法也是可以接受的。

而在一些背景下,平台是Windows 7 x64,MyProgram.exe运行良好,当我在MyProgram.exe项目目录中创build一个符号链接到OtherProgram的安装目录中的DLL。 当我尝试运行它没有符号链接,我得到“程序无法启动,因为OtherProgramDLL.dll从您的计算机丢失”错误。

任何意见或相关信息的链接非常感谢!

编辑:澄清:DLL在编译时不链接,此问题在运行时出现

Windows世界中有两种类型的动态链接:

  1. 加载时链接是在程序启动时自动加载DLL的时候。 Windows使用我将在下面讨论的特定算法找到这个DLL。
  2. 运行时链接是通过在代码中调用LoadLibrary专门加载DLL的。 类似的规则适用于如何找到该库,但您可以指定一个完全合格或相对合格的路径来控制搜索。

在加载时链接的情况下 ,MS建议您的程序的DLL存储在应用程序所在的同一目录中并从中加载。 如果这是可行的,这可能是你最好的选择。

如果这不起作用,还有其他几个选项, 这里概述 。 一种方法是通过将DLL放在工作目录或加载应用程序的目录中来利用搜索顺序。

您可以通过以下方式更改应用程序的工作目录:

  1. 创建一个快捷方式到您的应用
  2. 调出快捷方式的属性
  3. 编辑“开始”属性与DLL所在的目录。

当您使用快捷方式启动应用程序时,它将加载正确的DLL。

加载时间链接的其他选项包括:

  • 将清单添加到您的应用程序,该清单指定您的相关程序集的位置,或者,
  • 设置PATH

您可以将dll所在的目录添加到PATH环境变量。

你可以使用LoadLibrary ,但是你需要一种方法来保证DLL的位置。 这个维基百科文章提供了如何在加载后使用DLL的很好的例子。

我一直在努力解决同样的问题,并用LoadLibrarySetDllDirectory ,Qt的addLibraryPath等建议的方法找到了死胡同。 无论我尝试了什么,问题仍然是应用程序在实际运行代码之前检查了库(并没有找到它们),所以任何代码解决方案都会失败。

我几乎感到绝望,但后来发现了一个非常简单的方法,这可能也有助于像你这样的情况: 使用批处理文件! (或实际应用之前的类似加载器)

用于这种目的的Windows批处理文件可能如下所示:

 @echo off PATH=%PATH%;<PATH_TO_YOUR_LIB> <PATH_TO_YOUR_APP_EXE> 

/编辑:刚刚在Luchian的回答中看到了@SirDarius的评论,描述了这种方式,所以只要把我的批处理代码作为参考,所有的信用都发给他。

使用符号链接到第三方可执行文件

我发现Aaron Margosis所倡导的方法很有用。 看到:

使用NTFS连接修复64位版本的Windows上的应用程序兼容性问题

本质上,创建符号链接到每个依赖的第三方可执行文件。 将这些符号链接文件放置在您自己的可执行文件中。 除了目标文件名改变以外,即使未来更新改变了链接的目标,“软”符号链接也将解决加载时间依赖性问题。

我正在处理一个应用程序时遇到同样的问题。

我不想使用运行时加载,因为有几十个函数我需要手动创建函数指针。

Dibling先生提到的清单文件为我打开了一扇新的大门,但我遗憾地发现支持该功能的最早版本的Windows是Windows 7,它甚至不能在Vista上运行。

长话短说,一位熟悉Windows应用程序开发的朋友告诉我查找Delay-Loaded DLL ,结果是用最小的努力完美地解决了这个问题。 它会将DLL库的加载延迟到您手动执行的操作,或者第一次调用它的函数。 所以你只需要在你的DLL路径添加到搜索路径之前, SetDllDirectory帮助。

以下是使其工作的步骤:

1)通过makefile,cmake或VS属性页面(VS2015的Linker-> Input)指定要延迟加载到链接器的DLL。

2)在调用DLL之前,在程序开始时调用SetDllDirectory 。

延迟加载的DLL一直支持到VC6。 XP SP1后支持SetDllDirectory。