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

4

我有一个在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的路径?


1
请注意,将Delphi对象作为DLL参数传递通常是一个不好的想法。请改用包。关于加载时动态链接的所有建议仍然适用。 - Rob Kennedy
好的,没错...但是如果我改变包代码,我需要重新编译整个应用程序,甚至是主机应用程序吗?这就是为什么我使用 DLL 的原因,因为我不想重新编译主机应用程序。也许我需要更改 PrepareEmail 过程的代码,那么,我如何在不需要重新编译主机应用程序的情况下完成这个操作呢? - DelphiProgrammer
5个回答

11
首先,你没有"静态加载"任何东西。 DLL中的D代表动态;所有DLL都是动态链接的,无论如何。静态链接是DCU和OBJ文件包含在程序中的方式。你不能静态链接到DLL。
你正在谈论“加载时动态链接”,其中操作系统会根据程序导入表中列出的函数隐式地为您加载DLL,而不是“运行时动态链接”,其中您使用任何内容调用LoadLibrary。当您使用external指令定义函数时,您创建了一个导入表中的条目,据我所知,相对路径在那里是没有意义的。操作系统在加载时间(和运行时间)使用某些文档化的搜索顺序查找DLL。通常情况下,它是应用程序自己的目录,当前目录,系统目录,Windows目录,然后是PATH环境变量中的其他所有内容。
在您的情况下,当前目录和系统目录是同一个地方,并且您无法控制它们。不要将DLL放在Windows目录中;那里已经有足够多的不属于那里的东西了。
您最好将DLL放在与服务EXE相同的目录中。如果您不想这样做,那么您可以在该目录中放置足够启动程序的DLL,然后使用任何私有DLL目录稍后加载其他所有内容。

您可以将DLL文件放在其他地方,然后将该目录添加到PATH环境变量中。但请注意,该变量是共享资源,因此在更改之前请三思。


我相信它只处理当前目录和路径...这就是为什么%SystemRoot%\system32会被默认添加到路径中。 - skamradt
哎呀,我想系统目录已经被添加到路径中了,所以你可以在该目录下运行程序而不需要完整的路径。请参阅链接的文档。我想测试应该很容易:编辑您的路径以删除该目录并查看会出现什么问题。 - Rob Kennedy
在链接中描述的“文档搜索顺序”似乎非常清晰和明确。当前目录是首先查看的文件夹,路径文件夹是最后要检查的文件夹。在它们之间有许多系统定义的位置需要检查。我猜测系统目录默认添加到PATH变量中,以支持不实现操作系统等效文件搜索并(错误地)假定PATH变量是明确的应用程序。但这只是纯粹的推测。 - Deltics

2
请查看自Delphi 2010以来提供的延迟动态链接库。据我所知,您无法从特定路径加载dll,但是您可以在主机程序的第一行中修改环境路径变量,以包括dll所在的路径,然后再使用其导出函数。 将代码更改为显式加载dll并不难,并且您可以指定LoadLibrary API调用的完整路径。在同一篇文章中,您会发现隐式和显式dll加载的示例。

1

如果您将DLL路径放置在系统路径中,则无论您将其放置在何处都没有关系。只需注意,如果您更改服务的设置,则必须重新启动才能生效。

要编辑路径变量,请转到系统属性的高级选项卡(从“My Computer”右键单击属性),然后按“环境变量…”按钮。将系统变量“Path”更改为包括您想要存储DLL的目录。

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


0

0

值得一读的内容(从主要的MSDN文档页面链接)包括:

动态链接库重定向

它允许覆盖LoadLibrary中甚至是硬编码的DLL路径。如果对服务起作用,这可能解决所提出的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接