Delphi – always pass SEM_FAILCRITICALERRORS to SafeLoadLibrary
jpluimers - 19/May/2020
jpluimers - 19/May/2020
[SHOWTOGROUPS=4,20]
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:
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:
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:
ErrorMode values
There are many more modes you can pass to the [WayBack] SetErrorMode function (Windows):
My NOTE: Links to "anothers", was removed by default!
[/SHOWTOGROUPS]
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:
- [WayBack] Error regarding rtl240.bpl not found in stand alone version of GExperts Grep – twm’s blog
- [WayBack] Do not call SafeLoadLibrary(‘dllname.dll’) – twm’s blog
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 SetErrorMode in the Microsoft documentation.
- Note: On Linux, the Dummy argument is ignored.
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:
- [WayBack] If your floating point calculations differ after a trivial change – twm’s blog
- some additional comments at [WayBack] Today I had a curious bug: After changing the way GPS coordinates were read from a file (not calculated!) all of a sudden lots of unrelated floating poi… – Thomas Mueller (dummzeuch) – Google+
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:
- [WayBack] SetErrorMode function (Windows)
- [WayBack] GetErrorMode function (Windows)
- [WayBack] SetThreadErrorMode function (Windows)
- [WayBack] GetThreadErrorMode function (Windows)
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_FAILCRITICALERRORS0x0001The 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_NOALIGNMENTFAULTEXCEPT0x0004The 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_NOGPFAULTERRORBOX0x0002The system does not display the Windows Error Reporting dialog.
SEM_NOOPENFILEERRORBOX0x8000The 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.
My NOTE: Links to "anothers", was removed by default!
[/SHOWTOGROUPS]