任何人都知道是否可以在Delphi应用程序中优雅地测试和处理丢失的.dll文件?例如,我的代码有这个函数声明:
function KFUNC(Arg1, Arg2, Arg3, Arg4: DWord): longint stdcall; external 'KL2DLL32.DLL' name '_KFUNC@16';
Run Code Online (Sandbox Code Playgroud)
...当然需要在系统上找到dll文件KL2DLL32.DLL,否则我的应用程序将无法启动.我想知道是否有一些不同的方式来编码这个,所以我的应用程序可以测试dll文件的存在,然后相应地处理.显然,目标是让我的应用程序仍然正常启动,即使dll文件不存在.谢谢.
Dav*_*nan 11
导入导致使用所谓的加载时或隐式链接链接的函数.这是可执行文件包含元数据,告诉OS加载程序加载DLL,然后绑定到您命名的函数.如果此加载时链接过程失败,则无法加载可执行文件.
您有两个选项可以避免加载时链接,从而使您的程序能够适应链接故障.
延迟加载DLL
将delayed
指令添加到函数导入中.文件说:
要将包含该函数的库的加载推迟到实际需要该函数的时刻,请将延迟的指令附加到导入的函数:
Run Code Online (Sandbox Code Playgroud)function ExternalMethod(const SomeString: PChar): Integer; stdcall; external 'cstyle.dll' delayed;
delay确保在应用程序启动时不加载包含导入函数的库,而是在第一次调用函数时加载.
该文档包含更详细的其他有用主题,并介绍了如何处理错误:
显式加载和绑定到DLL
该delayed
指令只是让编译器安排显式加载DLL的简明方法.您可以使用LoadLibrary
和手动执行相同操作GetProcAddress
.
LoadLibrary
加载DLL.提供DLL的完整路径,或仅提供其名称.在后一种情况下,您依靠DLL搜索顺序来定位DLL.调用LoadLibrary
产生模块句柄.GetProcAddress
以获取指定函数指针的地址.您必须从步骤1提供模块句柄.FreeLibrary
卸载DLL.在每个步骤中,必须在出现错误时检查函数返回值.如何处理错误,请记录MSDN文档中的每个Win32 API函数(如上所述).例如,如果找不到DLL,则LoadLibrary
返回0
.您必须检测到并相应地处理后果.
讨论
虽然该delayed
指令非常方便,但我个人从未使用它.根据我的经验,每当我需要明确链接时,我总会发现我需要一些额外的灵活性delayed
.也许我的需求是特殊的,但是如果你发现自己倾向于明确地打电话给LoadLibrary
和,那就不要感到惊讶GetProcAddress
.
举个例子,就在今天我发现自己正在使用,LoadLibraryEx
因为我想传递LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR
旗帜.使用时无法使用那种细粒度控件delayed
.
当函数以这种方式声明时,您的程序对丢失的 DLL 无法执行任何操作。操作系统会在程序代码的任何部分开始执行之前尝试解析导入的 DLL 函数,因此您无法编写对此执行任何操作的代码。
不过,从 Delphi 2010 开始,您可以更改函数的声明以使用新的延迟加载功能。将delayed
指令添加到声明的末尾:
function KFUNC(Arg1, Arg2, Arg3, Arg4: DWord): longint stdcall;
external 'KL2DLL32.DLL' name '_KFUNC@16' delayed;
Run Code Online (Sandbox Code Playgroud)
如果您使用的是较旧的 Delphi 版本,那么您唯一的选择是在运行时加载 DLL 和函数,然后处理错误。
使用延迟的另一个好处是,有SetDliNotifyHook2
和SetDliFailureHook2
函数允许您分配挂钩,以便您可以分别处理运行时加载通知和失败。
因此,如果在运行时找不到给定的 DLL,甚至给定的函数,您可以记录错误,甚至用另一个 DLL 句柄或函数指针替换它来满足负载。
这两个选项将在另一个问题中进行更详细的讨论,该问题集中于仅在需要时使用 DLL。
归档时间: |
|
查看次数: |
999 次 |
最近记录: |