我有一个用 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的路径呢?
首先,您没有“静态加载”任何东西。 DLL中的D代表dynamic;无论如何,所有 DLL 都是动态链接的。静态链接是 DCU 和 OBJ 文件包含在程序中的方式。您无法静态链接到 DLL。
您正在谈论加载时动态链接,其中操作系统根据程序导入表中列出的函数隐式为您加载DLL,而不是运行时动态链接,您在其中调用
LoadLibrary
使用任何你想要的东西。当您使用 external
指令定义函数时,您会在导入表中创建一个条目,据我所知,相对路径是没有意义的。操作系统使用“特定记录的搜索顺序”在加载时(和运行时)查找 DLL。一般来说,它是应用程序自己的目录、当前目录、系统目录、Windows 目录,然后是 PATH 环境变量上的其他所有内容。
在你的情况下,当前目录和系统目录是同一个地方,你无论如何都无法控制它们。不要将 DLL 放在 Windows 目录中;已经有足够多不属于那里的东西了。
最好的办法是将 DLL 放在与服务 EXE 相同的目录中。如果您不想要,那么您可以在该目录中的一个 DLL 中放置足够的引导程序,然后使用您想要的任何私有 DLL 目录通过
LoadLibrary
加载其他所有内容。
您可以将 DLL 放在其他位置,然后将该目录添加到 PATH 环境变量中。不过,该变量是共享资源,因此在更改它之前请三思。
要编辑路径变量,请转到系统属性的高级选项卡(右键单击“我的电脑”中的属性),然后按“环境变量...”按钮。更改系统变量“Path”以包含您要存储 DLL 的目录。
解析DLL时,系统首先检查进程启动的当前目录,然后从左到右检查路径变量,然后使用在它运行的第一个目录中找到的DLL...这就是它起作用的原因当您将其放置在 C:\Windows\System32 中时。
项目 -> 选项 -> 应用程序 -> 清单
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>
如果你想定义你的库路径,这是正确的方法。不过,您无法动态定义它。