【问题标题】:How to put a relative path for a DLL statically loaded?如何为静态加载的 DLL 放置相对路径?
【发布时间】:2009-12-01 19:04:46
【问题描述】:

我有一个用 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 参数传递通常是一个坏主意。改用包。关于加载时动态链接的所有相同建议仍然适用。
  • 好的,没错...但是如果我更改了包代码,我是否需要重新编译整个应用程序,甚至是宿主应用程序?这就是我使用 DLL 的原因,因为我不想重新编译主机应用程序。也许我必须更改 PrepareEmail 程序的代码,那么,如何在不需要重新编译 Host 应用程序的情况下做到这一点???

标签: delphi dll


【解决方案1】:

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

您说的是加载时动态链接,操作系统会根据程序导入表中列出的函数为您隐式加载 DLL,而不是 运行时动态链接,你可以使用任何你想要的调用LoadLibrary。当您使用external 指令来定义您的函数时,您会在导入表中创建一个条目,据我所知,相对路径没有意义。操作系统在加载时(和运行时)使用certain documented search order 查找 DLL。一般来说,它是应用程序自己的目录、当前目录、系统目录、Windows 目录,然后是 PATH 环境变量中的所有其他内容。

在您的情况下,当前目录和系统目录是同一个地方,无论如何您都无法控制它们。不要将您的 DLL 放在 Windows 目录中;已经有足够多的不属于那里的东西了。

最好的办法是将 DLL 放在与服务 EXE 相同的目录中。如果您不想要,那么您可以在该目录中的一个 DLL 中放入足够的引导程序,然后稍后使用您想要的任何私有 DLL 目录使用LoadLibrary 加载其他所有内容。

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

【讨论】:

  • 我相信它只处理当前目录和路径...这就是为什么 %SystemRoot%\system32 默认添加到路径中的原因。
  • 天啊,我认为系统目录已添加到路径中,因此您可以在该目录中运行程序而无需完整路径。请参阅链接的文档。我想这很容易测试:编辑您的路径以删除该目录并查看哪些中断。
  • 链接中描述的“记录的搜索顺序”看起来非常清晰和明确。当前目录是查看的第一个文件夹,路径文件夹是要检查的最后一个文件夹。中间是检查的许多系统定义的位置。我的猜测是系统目录默认添加到 PATH 变量中,以支持不实现与操作系统等效的文件搜索的应用程序,并且(错误地)假设 PATH 变量是确定的。但这纯粹是猜测。
【解决方案2】:
  1. 看看delayed dynamic link libraries,自 Delphi 2010 起可用。AFAIK 您无法从非常特定的路径加载 dll,但您可以在主机程序的第一行修改环境路径变量以包含使用导出函数之前 dll 所在的路径。
  2. 更改代码以显式加载 dll 并不困难,您可以指定 LoadLibrary API 调用的完整路径。您将在 same article 中找到一个隐式和显式 dll 加载示例。

【讨论】:

    【解决方案3】:

    如果您将 DLL 的路径放在系统路径中,那么放在哪里都没有关系。请注意,如果您对服务进行更改,则必须重新启动才能生效。

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

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

    【讨论】:

      【解决方案4】:

      在此处查看 Windows 如何加载 DLL:

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

      SetDllDirectory() 可能会对您有所帮助,但它在 XP SP1 之前不可用。

      【讨论】:

        【解决方案5】:

        另外值得一读(链接自 MSDN 主文档页面)是:

        Dynamic-Link Library Redirection

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

        【讨论】:

          猜你喜欢
          • 2011-02-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-12-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多