如何为静态加载的DLL放置相对路径?

问题描述 投票:0回答:6

我有一个用 Delphi 7/Windows XP 制作的 DLL,我想将其静态加载到 Windows 上的主机应用程序中(也是用 Delphi 制作的)。我正在使用这行代码:

procedure Prepare_HTML_Email(var MailMessage : TIdMessage;
  const FileAddress, aDetail, aAlarmType : String); stdcall; external DLL_ADDRESS;

其中

DLL_ADDRESS
必须是 DLL 所在的位置。但此时我有一个问题。主机应用程序是一个服务,因此它运行在
C:\WINDOWS\System32
中,但我想将DLL放在另一个目录中,而不是放在
C:\WINDOWS\System32
中。 “external”关键字不允许其后跟函数,它只允许常量表达式。那么,如何获取DLL的路径呢?

delphi dll
6个回答
11
投票

首先,您没有“静态加载”任何东西。 DLL中的D代表dynamic;无论如何,所有 DLL 都是动态链接的。静态链接是 DCU 和 OBJ 文件包含在程序中的方式。您无法静态链接到 DLL。

您正在谈论加载时动态链接,其中操作系统根据程序导入表中列出的函数隐式为您加载DLL,而不是运行时动态链接,您在其中调用

LoadLibrary 
使用任何你想要的东西。当您使用
external
指令定义函数时,您会在导入表中创建一个条目,据我所知,相对路径是没有意义的。操作系统使用“特定记录的搜索顺序”在加载时(和运行时)查找 DLL。一般来说,它是应用程序自己的目录、当前目录、系统目录、Windows 目录,然后是 PATH 环境变量上的其他所有内容。 在你的情况下,当前目录和系统目录是同一个地方,你无论如何都无法控制它们。不要将 DLL 放在 Windows 目录中;已经有足够多不属于那里的东西了。

最好的办法是将 DLL 放在与服务 EXE 相同的目录中。如果您不想要,那么您可以在该目录中的一个 DLL 中放置足够的引导程序,然后使用您想要的任何私有 DLL 目录通过

LoadLibrary

加载其他所有内容。


您可以将 DLL 放在其他位置,然后将该目录添加到 PATH 环境变量中。不过,该变量是共享资源,因此在更改它之前请三思。


2
投票
看看
    延迟动态链接库
  1. ,自 Delphi 2010 起可用。据我所知,您无法从非常特定的路径加载 dll,但您可以修改主机程序第一行的环境路径变量以包含在使用 dll 的导出函数之前,该 dll 所在的路径。 更改代码以显式加载 dll 并不困难,您可以指定 LoadLibrary API 调用的完整路径。您将在
  2. 同一篇文章
  3. 中找到隐式和显式 dll 加载的示例。

1
投票

要编辑路径变量,请转到系统属性的高级选项卡(右键单击“我的电脑”中的属性),然后按“环境变量...”按钮。更改系统变量“Path”以包含您要存储 DLL 的目录。

解析DLL时,系统首先检查进程启动的当前目录,然后从左到右检查路径变量,然后使用在它运行的第一个目录中找到的DLL...这就是它起作用的原因当您将其放置在 C:\Windows\System32 中时。


0
投票

http://msdn.microsoft.com/en-us/library/ms682586(VS.85).aspx

SetDllDirectory() 可能会帮助你,但它在 XP SP1 之前不可用。


0
投票

动态链接库重定向

甚至允许覆盖 LoadLibrary 中的硬编码 DLL 路径。如果它适用于服务,这可以解决相关问题。


0
投票

项目 -> 选项 -> 应用程序 -> 清单

Manifest File

组合框中,选择“custom”。

自定义清单

编辑中,告知清单文件名(application_name.manifest)。 如果您使用的是旧版 Delphi,请考虑将清单文件包含在要添加为资源的“.rc”文件中。

清单文件如下所示:

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <!-- Your libraries --> <file name="your_dll_name.dll" loadFrom="the_dll_path" /> <!-- System libraries --> <file name="version.dll" loadFrom="%SystemRoot%\system32\" /> <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> <application> <!-- Windows 10 --> <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/> <!-- Windows 8.1 --> <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> <!-- Windows Vista --> <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> <!-- Windows 7 --> <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/> <!-- Windows 8 --> <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/> </application> </compatibility> </assembly>

如果你想定义你的库路径,这是正确的方法。不过,您无法动态定义它。

© www.soinside.com 2019 - 2024. All rights reserved.