[英]possible to handle missing dll file gracefully in Delphi application?
Anyone know if its possible to gracefully test for and handle a missing .dll file in a Delphi application? 任何人都知道是否可以在Delphi应用程序中优雅地测试和处理丢失的.dll文件? For example, my code has this function declaration:
例如,我的代码有这个函数声明:
function KFUNC(Arg1, Arg2, Arg3, Arg4: DWord): longint stdcall; external 'KL2DLL32.DLL' name '_KFUNC@16';
...which of course requires the dll file KL2DLL32.DLL to be found on the system, otherwise my application wont start. ...当然需要在系统上找到dll文件KL2DLL32.DLL,否则我的应用程序将无法启动。 Im wondering if theres some different way to code this, so my application could test for the dll file's existence, and then handle accordingly.
我想知道是否有一些不同的方式来编码这个,所以我的应用程序可以测试dll文件的存在,然后相应地处理。 Obviously, the goal would be have my application still start normally even if the dll file isn't there.
显然,目标是让我的应用程序仍然正常启动,即使dll文件不存在。 Thanks.
谢谢。
Your import results in the function being linked using what is known as load-time or implicit linking. 导入导致使用所谓的加载时或隐式链接链接的函数。 That is the executable contains meta data that tells the OS loader to load the DLL, and then bind to the functions that you named.
这是可执行文件包含元数据,告诉OS加载程序加载DLL,然后绑定到您命名的函数。 If this load-time linking process fails, then the executable cannot be loaded.
如果此加载时链接过程失败,则无法加载可执行文件。
You have a couple of options to avoid load-time linking, and thereby allow your program to be resilient to linking failures. 您有两个选项可以避免加载时链接,从而使您的程序能够适应链接故障。
Delay-loading the DLL 延迟加载DLL
Add the delayed
directive to your function import. 将
delayed
指令添加到函数导入中。 The documentation says: 文件说:
To postpone the loading of the library that contains the function to the moment the function is actually needed, append the delayed directive to the imported function:
要将包含该函数的库的加载推迟到实际需要该函数的时刻,请将延迟指令附加到导入的函数:
function ExternalMethod(const SomeString: PChar): Integer; stdcall; external 'cstyle.dll' delayed;
delayed ensures that the library that contains the imported function is not loaded at application startup, but rather when the first call to the function is made.
delay确保在应用程序启动时不加载包含导入函数的库,而是在第一次调用函数时加载。
The documentation contains other useful topics that go into more detail, and cover how to handle errors: 该文档包含更详细的其他有用主题,并介绍了如何处理错误:
Explicit loading and binding to the DLL 显式加载和绑定到DLL
The delayed
directive is merely a concise way to get the compiler to arrange explicit loading of your DLL. delayed
指令只是让编译器安排显式加载DLL的简明方法。 You can do the same yourself manually using LoadLibrary
and GetProcAddress
. 您可以使用
LoadLibrary
和GetProcAddress
手动执行相同的操作。
LoadLibrary
to load the DLL. LoadLibrary
以加载DLL。 Either supply a full path to the DLL, or just its name. LoadLibrary
yields a module handle. LoadLibrary
的调用产生了一个模块句柄。 GetProcAddress
to obtain the address of a named function pointer. GetProcAddress
以获取指定函数指针的地址。 You must supply the module handle from step 1. FreeLibrary
to unload the DLL. FreeLibrary
卸载DLL。 At each step of the way you must check the function return values in case of error. 在每个步骤中,必须在出现错误时检查函数返回值。 How to handle errors is documented for each Win32 API function in the MSDN documentation (as linked to above).
如何处理错误,请记录MSDN文档中的每个Win32 API函数(如上所述)。 For example, if the DLL cannot be found, then
LoadLibrary
returns 0
. 例如,如果找不到DLL,则
LoadLibrary
返回0
。 You must detect that and deal with the consequences accordingly. 您必须检测到并相应地处理后果。
Discussion 讨论
Although the delayed
directive is very convenient, I personally have never used it. 虽然
delayed
指令非常方便,但我个人从未使用它。 In my experience, whenever I have needed to link explicitly I've always found that I needed some extra flexibility that is not offered by delayed
. 根据我的经验,每当我需要明确链接时,我总是发现我需要一些
delayed
不提供的额外灵活性。 Perhaps my needs are special, but do not be surprised if you find yourself leaning towards explicit calls to LoadLibrary
and GetProcAddress
. 也许我的需求很特殊,但如果你发现自己倾向于显式调用
LoadLibrary
和GetProcAddress
,也不要感到惊讶。
As an example, just today I found myself using LoadLibraryEx
because I wanted to pass the LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR
flag. 作为一个例子,就在今天我发现自己使用
LoadLibraryEx
因为我想传递LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR
标志。 That sort of fine grained control is not available when you use delayed
. 当您使用
delayed
时,这种细粒度控制不可用。
When the function is declared like that, there's nothing your program can do about a missing DLL. 当声明这样的函数时,你的程序对丢失的DLL没有任何作用。 The OS attempts to resolve the imported DLL function before any bit of your program's code begins to execute, so there's no code you can write that would do anything about it.
操作系统尝试在程序代码的任何位开始执行之前解析导入的DLL函数,因此没有可编写的代码可以对其执行任何操作。
As of Delphi 2010, though, you can change the function's declaration to use the new delayed loading feature. 但是,从Delphi 2010开始,您可以更改函数的声明以使用新的延迟加载功能。 Add the
delayed
directive to the end of the declaration: 将
delayed
指令添加到声明的末尾:
function KFUNC(Arg1, Arg2, Arg3, Arg4: DWord): longint stdcall;
external 'KL2DLL32.DLL' name '_KFUNC@16' delayed;
If you're using an older Delphi version, then your only option is to load the DLL and the function at run time, and then handle the errors. 如果您使用的是较旧的Delphi版本,那么您唯一的选择是在运行时加载DLL和函数,然后处理错误。
Another benefit of using delayed is that there are SetDliNotifyHook2
and SetDliFailureHook2
functions that allow you to assign hooks so you can handle run-time load notifications and failures, respectively. 使用延迟的另一个好处是
SetDliNotifyHook2
和SetDliFailureHook2
函数允许您分配挂钩,以便分别处理运行时加载通知和失败。
So, if a given DLL, or even a given function, is not found at runtime, you can log an error, even substitute it with another DLL handle or function pointer to satisfy the load. 因此,如果在运行时未找到给定的DLL或甚至给定的函数,则可以记录错误,甚至将其替换为另一个DLL句柄或函数指针以满足负载。
Both options are discussed in more detail in another question centering on using a DLL only when required . 在仅在需要时使用DLL的另一个问题中更详细地讨论了这两个选项。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.