But sometimes, for some reason, you may want to make a background application as a regular user application. In this case, you would not want your application to show any error messages.
Test code
To test your application's behavior with fatal errors - you can use the following code:// A thread function function Crash(Arg: Pointer): Integer; stdcall; begin // Artificially raise a test exception PInteger(nil)^ := 0; Result := 0; end; function TForm1.Button1Click(Sender: TObject); var TID: Cardinal; begin // Create a new thread with the entry point specified above CloseHandle(CreateThread(nil, 0, @Crash, nil, 0, TID)); end;This code creates a new
Crash
thread using the CreateThread
system function. Threads created by the CreateThread
function do not have any exception handlers, so if such a thread throws an exception and your thread's function code does not handle it, the exception is propagated to the system (a global handler), which results in a fatal exception.In this case, our test code throws an
EAccessViolation
exception, trying to write an integer (0) to a null pointer (nil).Apps with EurekaLog
If your project has EurekaLog on board, your application will behave differently, because EurekaLog will install its own global exception handler. It is much more difficult to get a fatal exception in a project with EurekaLog, so it is better to disable EurekaLog for testing.Note that adding EurekaLog to your application does not guarantee that the dialog shown above will never appear for your application. EurekaLog runs from within the process. It means that there will always be a chance of a situation so bad that exception handlers inside the application cannot be called, which will lead to the process being closed from outside (by the system). For example:
// Calls a test exception procedure Kaboom; begin raise Exception.Create('Error Message'); end; // Damages CPU stack and calls the Kaboom function procedure Test; assembler; asm // We simulate a "buffer overflow" bug mov [esp+4], 0; mov [esp+8], 0; mov [esp+12], 0; call Kaboom; end; // A test thread's function function T(I: Integer): Integer; stdcall; begin try Test; except // Does not matter end; Result := 0; end;This code will crash the application even with EurekaLog on board, since this code corrupts the system records of exception handlers. Therefore, when the
Kaboom
function raises a test exception, the system cannot call the exception handler (marked as "Does not matter" in the code example) and has no choice but to close the process.Disabling system reports
So, to prevent your application from showing the "Program has stopped working" dialog, you can disable the WER (Windows Error Reporting) service for your application. You can do this by calling the following code when your application starts:SetErrorMode(GetErrorMode or SEM_NOGPFAULTERRORBOX);The
SetErrorMode
function specifies how the system or process should handle fatal errors. In particular, the SEM_NOGPFAULTERRORBOX
flag specifies that the system should not generate Windows error reports.Note that you must modify the already defined process mode, you cannot rewrite it completely from scratch, removing flags that you know nothing about. For example, the following code is WRONG:
SetErrorMode(SEM_NOGPFAULTERRORBOX);If you need to turn off this mode, you should use a code like this:
SetErrorMode(GetErrorMode and (not SEM_NOGPFAULTERRORBOX));Note that enabling this mode will completely disable the WER (Windows Error Reporting) service for your application.
Disabling only visual dialogs
If you do not want to completely disable WER for your application (for example, if you want to use the WER system logs to view the list of "crashes" of your application), you can disable only visual dialogs. This can be done by calling the following code:var Flags: Cardinal; begin if Failed(WerGetFlags(GetCurrentProcess, Flags)) then Flags := 0; WerSetFlags((Flags or WER_FAULT_REPORTING_NO_UI) and (not WER_FAULT_REPORTING_ALWAYS_SHOW_UI));The
WerSetFlags
function sets the Windows Error Reporting (WER) options for the current process.As with
SetErrorMode
, you should not call WerSetFlags
blindly, overriding already set modes of operation, you should only change those modes that you want to change. Specifically, the code in the example above sets the WER_FAULT_REPORTING_NO_UI
flag and clears the WER_FAULT_REPORTING_ALWAYS_SHOW_UI
flag. The WER_FAULT_REPORTING_NO_UI
flag tells WER to never show the error reporting user interface for this process. The flag WER_FAULT_REPORTING_ALWAYS_SHOW_UI
, on the contrary, asks WER to always show the error reporting user interface for this process.The
WerSetFlags
function, and the WER_FAULT_REPORTING_NO_UI
, WER_FAULT_REPORTING_ALWAYS_SHOW_UI
flags are not declared in the standard Delphi header files, but you can declare them yourself, import them from the JEDI Windows API Library or from EurekaLog. For example (for EurekaLog):uses EWER; var Flags: Cardinal; begin // You should call this function before using anything from EWER unit InitWER; // imports WER functions // Will be False for very old Windows (like 2000 and XP) if Assigned(WerSetFlags) then begin if Failed(WerGetFlags(GetCurrentProcess, Flags)) then Flags := 0; WerSetFlags((Flags or WER_FAULT_REPORTING_NO_UI) and (not WER_FAULT_REPORTING_ALWAYS_SHOW_UI)); end;
Disabling dialogs in EurekaLog
If EurekaLog is added to your project, it can also show dialogs about errors. You can disable these dialogs. First, of course, you should switch the main visual dialog to "None" in the project settings (disables the exception dialog).If you have configured sending reports in your project, then you should disable visual support for sending reports by disabling the "Show send progress", "Show success message", and "Show failure message" options.
Finally, in some rare cases, EurekaLog can show simple messages (via
MessageBox
). These dialogs can also be disabled. To do this, you need to enable hooks for non-visual applications ("[Non-visual] Hides MessageBoxes") in the hooks settings. This option is enabled automatically if you select a suitable profile (for example, a system service) during the initial project setup for EurekaLog, but if you select the standard "VCL Forms application" profile, you need to enable this setting manually.P.S. If you are developing a service, you will probably want to use the system logging setup dialog instead of disabling the dialog completely.
P.P.S. Since you are writing a background application which runs as a standard user application, system restart settings will not be applied to your application. So it will be simply terminated in case of a crash. You may set up restart settings in EurekaLog, but you should be aware that these settings will only work if your application shut downs more or less gracefully (under control of EurekaLog). For example, we had a code example above that illustrates how EurekaLog-enabled application can perform a fatal crash. Your application will be closed by an external process (the system) in that case, so any user code from within your process won't be called (including EurekaLog). It means that if you want a reliable way to restart your application - you have to have some sort of external monitor process, which will restart your application in case of fatal crash.
See also: