C++ 在程序启动时从另一个目录加载 DLL
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10606304/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Load a DLL from another directory at program start
提问by CJ McAllister
My basic issue is this: my program (MyProgram.exe) has a dependency on a DLL from another program (OtherProgram), and I'm trying to avoid repackaging a new DLL every time OtherProgram updates. I'd like to have MyProgram.exe link in OtherProgram's DLL when it launches, but I'm not completely sure that Windows allows for this. So if there is some kind of workaround that would also be acceptable.
我的基本问题是:我的程序 (MyProgram.exe) 依赖于另一个程序 (OtherProgram) 的 DLL,并且我试图避免每次 OtherProgram 更新时重新打包新的 DLL。我想在其他程序的 DLL 启动时有 MyProgram.exe 链接,但我不完全确定 Windows 是否允许这样做。因此,如果有某种解决方法也是可以接受的。
And just for some background, the platform is Windows 7 x64, and MyProgram.exe runs fine when I create a symlink in the MyProgram.exe project directory to the DLL in OtherProgram's install directory. When I try to run it without the symlink, I get the "program can't start because OtherProgramDLL.dll is missing from your computer" error.
对于一些背景,平台是 Windows 7 x64,当我在 MyProgram.exe 项目目录中创建指向 OtherProgram 安装目录中的 DLL 的符号链接时,MyProgram.exe 运行良好。当我尝试在没有符号链接的情况下运行它时,出现“程序无法启动,因为您的计算机中缺少 OtherProgramDLL.dll”错误。
Any advice or links to relevant info is greatly appreciated!
非常感谢任何建议或相关信息的链接!
EDIT: Clarification: the DLL is not linked at compile-time, this issue crops up at runtime
编辑:澄清:DLL 在编译时没有链接,这个问题在运行时出现
回答by John Dibling
There are two types of dynamic linking in the Windows world:
Windows 世界中有两种类型的动态链接:
- Load-Timelinking is when a DLL is loaded automatically when your program starts up. Windows finds this DLL using a specific algorithm I'll discuss below.
- Run-Timelinking is when youspecifically load a DLL by calling
LoadLibrary
in your code. Similar rules apply as to how the library is found, but you can specify a fully-qualified or relatively-qualified path to control the search.
- 加载时链接是在程序启动时自动加载 DLL。Windows 使用我将在下面讨论的特定算法找到此 DLL。
- 运行时链接是当您通过调用
LoadLibrary
代码专门加载 DLL 时。类似的规则适用于如何找到库,但您可以指定完全限定或相对限定的路径来控制搜索。
In the case of Load-Time linking, MS recommends that your program's DLLs are stored in and loaded from the same directory where your application is loaded from. If this is at all workable, this is probably your best option.
在加载时链接的情况下,MS 建议您的程序的 DLL 存储在您的应用程序加载的同一目录中并从该目录加载。如果这完全可行,这可能是您的最佳选择。
If that doesn't work, there are several other options, outlined here. One is to leverage the search order by putting the DLL in either the working directory or the directory where the application was loaded from.
如果这不起作用,还有其他几个选项,概述here。一种是通过将 DLL 放在工作目录或加载应用程序的目录中来利用搜索顺序。
You can change the working directory of an application by:
您可以通过以下方式更改应用程序的工作目录:
- Create a shortcut to your application.
- Bring up the shortcut's properties
- Edit the "Start in" property with the directory where the DLL is located.
- 创建应用程序的快捷方式。
- 调出快捷方式的属性
- 使用 DLL 所在的目录编辑“开始于”属性。
When you launch your application using the shortcut, it will load the right DLL.
当您使用快捷方式启动应用程序时,它将加载正确的 DLL。
Other options for load-time linking include:
加载时链接的其他选项包括:
- Adding a manifest to your application which specifies where your dependent assembliesare, or,
- Setting the
PATH
.
- 向您的应用程序添加一个清单,该清单指定您的依赖程序集所在的位置,或者,
- 设置
PATH
.
回答by Eckstein
You could use LoadLibrary, but you would need a way to guarantee the DLL's location. This Wikipedia articleprovides good example on how to use the DLL after it has been loaded.
您可以使用LoadLibrary,但您需要一种方法来保证 DLL 的位置。这篇维基百科文章提供了一个很好的例子,说明如何在加载后使用 DLL。
回答by Franz B.
I have struggled with the same problem and also found a dead end with the suggested methods like LoadLibrary
, SetDllDirectory
, Qt's addLibraryPath
and others. Regardless of what I tried, the problem still remained that the application checked the libraries (and didn't find them) before actually running the code, so any code solution was bound to fail.
我一直在为同样的问题而苦苦挣扎,并且还发现建议的方法(如LoadLibrary
、SetDllDirectory
、 QtaddLibraryPath
和其他方法)陷入了死胡同。不管我尝试了什么,问题仍然存在,即应用程序在实际运行代码之前检查了库(并没有找到它们),因此任何代码解决方案都注定会失败。
I almost got desperate, but then discovered an extremely easy approach which might also be helpful in cases like yours: Use a batch file!(or a similar loader before the actual application)
我几乎绝望了,但后来发现了一种非常简单的方法,它可能对您这样的情况也有帮助:使用批处理文件!(或实际应用之前的类似加载器)
A Windows batch file for such a purpose could look like this:
用于此目的的 Windows 批处理文件可能如下所示:
@echo off
PATH=%PATH%;<PATH_TO_YOUR_LIB>
<PATH_TO_YOUR_APP_EXE>
/edit: Just saw @SirDariuscomment in Luchian's answerwhich describes that way, so just take my batch code bit as a reference and all credits go to him.
/edit:刚刚在Luchian 的回答中看到了@SirDarius评论,它描述了这种方式,所以只需将我的批处理代码作为参考,所有功劳都归他所有。
回答by Luchian Grigore
You can add the directory where the dll is located to the PATH
environment variable.
您可以将dll所在的目录添加到PATH
环境变量中。
回答by logicor
I have the same problem with one application I am working on.
我正在处理的一个应用程序遇到了同样的问题。
I do not want to use runtime loading because there are tens of functions I would need to manually create function pointer for.
我不想使用运行时加载,因为我需要为数十个函数手动创建函数指针。
Mr Dibling's mention of manifest file opened a new door for me but I sadly found out that the oldest version of windows that supports the feature is Windows 7. It won't even work on Vista.
Dibling 先生提到的清单文件为我打开了一扇新的大门,但我遗憾地发现支持该功能的最旧版本的 Windows 是 Windows 7。它甚至无法在 Vista 上运行。
Long story short, a friend familiar with Windows Application development told me to look up Delay-Loaded DLL, which turns out to solve the problem perfectly with minimal effort. It delays the loading of DLL library to either the point you manually do, or the first time its function is called. So you just need to add your DLL path to the search path before that happens, where SetDllDirectoryhelps.
长话短说,一位熟悉 Windows 应用程序开发的朋友告诉我查找Delay-Loaded DLL,结果证明它以最少的努力完美地解决了问题。它将 DLL 库的加载延迟到您手动执行的点,或者第一次调用其函数时。因此,您只需要在此之前将您的 DLL 路径添加到搜索路径中,其中SetDllDirectory会有所帮助。
Here is the steps to make it work:
以下是使其工作的步骤:
1) Specify the DLL to be delay-loaded to linker, either through your makefile, cmake or VS property page (Linker->Input of VS2015)
1) 指定要延迟加载到链接器的 DLL,通过您的 makefile、cmake 或 VS 属性页(链接器->VS2015 的输入)
2) Call SetDllDirectoryat the beginning of your program, before any call to the DLL is made.
2)在对 DLL 进行任何调用之前,在程序开始时调用SetDllDirectory。
Delay-loaded DLL is supported all the way back to VC6. SetDllDirectory is supported after XP SP1.
一直支持延迟加载的 DLL 回到 VC6。XP SP1 之后支持 SetDllDirectory。
回答by ergohack
Use Symbolic Links to the 3rd Party Executables
使用符号链接到第 3 方可执行文件
I found the approach advocated by Aaron Margosisuseful. See:
我发现Aaron Margosis提倡的方法很有用。看:
Using NTFS Junctions to Fix Application Compatibility Issues on 64-bit Editions of Windows
Essentially, create symbolic links to each of the dependent 3rd Party executables. Place these symbolic link files in and amongst your own dependent executable files. Except for filename changes to the targets, the 'soft' symbolic links will resolve the load-time dependencies even as the target of the links are changed by future updates.
本质上,为每个依赖的第 3 方可执行文件创建符号链接。将这些符号链接文件放在您自己的相关可执行文件中。除了对目标的文件名更改外,“软”符号链接将解决加载时依赖性,即使链接的目标因未来更新而更改。