The below is based on [WayBack] delphi – Is there any way to catch the error if loading a dll cannot find a dependency? – Stack Overflow which I got via:
The problem is that the [WayBack] SysUtils.SafeLoadLibrary Function (present since at least Delphi 2007, and a wrapper around the [WayBack] LoadLibrary function (Windows)) does many good things – maybe even too many – so you need to take all of them into account:
function SafeLoadLibrary(const FileName: string; ErrorMode: UINT = SEM_NOOPENFILEERRORBOX): HMODULE;
SafeLoadLibrary
loads a Windows DLL or Linux shared object file, as specified by Filename
.
SafeLoadLibrary
preserves the current FPU control word, preventing library initialization code from permanently overwriting precision and exception masks.
- Note:
- On Windows,
SafeLoadLibrary
temporarily sets the system error mode to ErrorMode
. The default, SEM_NOOPENFILEERRORBOX
, suppresses error dialogs. The previous error mode is restored before SafeLoadLibrary
exits. For a list of error modes, refer to [Wayback1/Wayback2] SetErrorMode in the Microsoft documentation.
- Note: On Linux, the
Dummy
argument is ignored.
Most important tips
Do not ever pass 0
(the number zero) as ErrorMode
; I’ve seen lots of applications just passing zero for parameters they are not sure about, but in this case it is the worst solution as it will show all errors as a popup.
Do not forget a parameter either: the default value SEM_NOOPENFILEERRORBOX
will only suppress a message box when it fails to find a file. But it will fail to enable SEM_FAILCRITICALERRORS
which is what you really want.
Loading DLLs from resources
LoadLibrary
and SafeLoadLibrary
load the DLL from a file. But what if you want to load it from a resource?
Then this post from Thomas Mueller applies: he adopted the SafeLoadLibrary logic to load from a resource:
Other thoughts to keep in mind
The way Delphi sets the FPU control word is not thread safe: QualityCentral Report # 106943: Set8087CW/SetMXCSR are not thread-safe (you could work around in your implementation by using thread safe versions like mentioned in [WayBack] FastMM / Discussion / Open Discussion:Call to GetStackTrace changes 8087CW).
Calling SetErrorMode
sets a global application wide setting (by default including all threads) of error code, so it is better to either:
- decide for your whole application up front which error mode to use, save it and use the same value everywhere:
Because the error mode is set for the entire process, you must ensure that multi-threaded applications do not set different error-mode flags. Doing so can lead to inconsistent error handling.
- decide between the global or local error mode methods:
Second, SEM_FAILCRITICALERRORS
prevents an error to pop up when dependencies of the loaded file are not available. You might want to combine (bitwise or
) it with other values like SEM_NOGPFAULTERRORBOX
.
ErrorMode values
There are many more modes you can pass to the [WayBack] SetErrorMode function (Windows):
-
Value |
Meaning |
- 0
|
Use the system default, which is to display all error dialog boxes. |
- SEM_FAILCRITICALERRORS
- 0x0001
|
The system does not display the critical-error-handler message box. Instead, the system sends the error to the calling process.
Best practice is that all applications call the process-wide SetErrorMode function with a parameter of SEM_FAILCRITICALERRORS at startup. This is to prevent error mode dialogs from hanging the application. |
- SEM_NOALIGNMENTFAULTEXCEPT
- 0x0004
|
The system automatically fixes memory alignment faults and makes them invisible to the application. It does this for the calling process and any descendant processes. This feature is only supported by certain processor architectures. For more information, see the Remarks section.
After this value is set for a process, subsequent attempts to clear the value are ignored. |
- SEM_NOGPFAULTERRORBOX
- 0x0002
|
The system does not display the Windows Error Reporting dialog. |
- SEM_NOOPENFILEERRORBOX
- 0x8000
|
The OpenFile function does not display a message box when it fails to find a file. Instead, the error is returned to the caller. This error mode overrides the OF_PROMPT flag. |
–jeroen
all via:
Related: