Root > How to... > ...override exception message?

...override exception message?

Previous pageReturn to chapter overviewNext page   

There are cases when you need to change the message of the exception. For example:

You want to hide technical details from user. For example, show "Sorry, there was a problem" instead of technical gibberish like "Access Violation at address 12345678";
You want to add more details or enhance the description. For example, add a file name to the "File open error".

 

EurekaLog offers various ways to change the exception message:

1. Override. Overriding exception message will show new message to a user in various dialogs. However, the bug report will contain the original exception message. E.g. a user will see "Sorry, the was a problem", while you (as developer) will see (via bug report) "Access Violation at address 12345678". In other words, exception's message will be different in EurekaLog and exception object.
2. Replace. Replacing exception message will replace the exception message itself. Both bug report and dialog will show the same changed message. This is typically used if you need to update the exception by adding additional information. In other words, both EurekaLog and exception object will use the same message.

 


 

1. Overriding the message

 

Overriding exception message will show new message to a user in various dialogs. However, the bug report will contain the original exception message. E.g. a user will see "Sorry, the was a problem", while you (as developer) will see (via bug report) "Access Violation at address 12345678". In other words, exception's message will be different in EurekaLog and exception object.

 

Override message for all exceptions

If you want to hide all exception messages and show something like "Sorry, there was an error in the application" instead - you can use exception filters. Simply add a new filter to override message for all exceptions:

1. Open Project / EurekaLog options;
2. Go to Advanced / Exception filters tab;
3. Click on the "Add" button;
4. Enter "Exception" (without quotes) as "Exception Class" and make sure that "Include child classes" option is checked;
5. Switch to "Altering behaviour" tab and set "Override Exception Message" option to whatever text you like.
6. Don't change anything else and save the new filter.

 

You can also do the same with the following code at run-time:

 

uses
  EModules, // for CurrentEurekaLogOptions
  ETypes;   // for TEurekaExceptionFilter
 
procedure AddFilters;
var
  Filter: TEurekaExceptionFilter;
begin
  FillChar(Filter, SizeOf(Filter), 0);
 
  // Matching:
  Filter.Active := True;
  Filter.ExceptionClassName := 'Exception';
  Filter.IncludeChildClasses := True;
 
  // Altering behaviour:
  Filter.HandlerType := fhtEurekaLog;
  Filter.ExceptionMessage := 'Sorry, there was a problem.';
  Filter.DialogType := edtUnchanged;
  Filter.ActionType := fatUnchanged;
 
  CurrentEurekaLogOptions.ExceptionsFilters.Add(Filter);
 
  Finalize(Filter);
end;
 
initialization
  AddFilters;
end.

 

Notes:

If you are going to add more filters later - make sure that this filter (for the "Exception" class) is the last one to be added;
If you are going to use any other filter - don't forget to also specify the "Override Exception Message" option for each filter.

 

 

Override message only for a specific exception

There are several ways to override message of a particular exception. You need to be able to identify the desired exception - either via its class/other properties or via throwing location.

 

 

Option1: use exception filters

If you can identify the exception by using the exception filters - you can do the same as above, but replacing "Exception" class with any other info that can identify your exceptions.

 

 

Option2: use custom attributes

If you need to replace exception message only for exceptions of the specific class - you can use custom attributes (available in modern IDEs).

 

uses
  EClasses; // for EurekaLogMessage
 
type
  [EurekaLogMessage('Sorry, there was a problem.')]
  EMyException = class(Exception);
 
procedure TForm1.Button1Click(Sender: TObject);
begin
  raise EMyException.Create('Error Message');
end;

 

 

Option 3: use event handlers

If you need complete control over properties of the exception - you can use event handlers:

 

uses
  EEvents,    // for RegisterEventExceptionNotify
  EException; // for TEurekaExceptionInfo
 
procedure OverrideMessage(const ACustom: Pointer;
  AExceptionInfo: TEurekaExceptionInfo;
  var AHandle: Boolean;
  var ACallNextHandler: Boolean);
begin
  // Find our exception

  // This is only an example

  // You can add more checks
  if AExceptionInfo.ExceptionClass = 'EMyException' then
  begin
    // Override exception message
    AExceptionInfo.AdditionalInfo := 'Sorry, there was a problem.';

    // Tells EurekaLog to use the .AdditionalInfo property instead of real message
    AExceptionInfo.Options.UseExceptionComments := True;
  end;
end;
 
initialization
  RegisterEventExceptionNotify(nil, OverrideMessage);
end.

 

Here is an example of how you can check various properties of your exception (we recommend to specify as much as you can):

 

procedure OverrideMessage(const ACustom: Pointer; 

  AExceptionInfo: TEurekaExceptionInfo; 

  var AHandle: Boolean; 

  var ACallNextHandler: Boolean);
begin

  if // check exception class name
     (AExceptionInfo.ExceptionClass = 'EOSError'and 

     // check exception message
     (AExceptionInfo.ExceptionMessage = 'Access Denied'and 

     // check that there is exception object

     (AExceptionInfo.ExceptionObject <> niland 

     // check that it is a Delphi/Builder object
     (AExceptionInfo.ExceptionNative) and 

     // check exception class 

     // (only for .ExceptionNative = True and .ExceptionObject <> nil)
     (TObject(AExceptionInfo.ExceptionObject).InheritsFrom(EOSError)) and 

     // check any additional exception properties
     (EOSError(AExceptionInfo.ExceptionObject).ErrorCode = ERROR_ACCESS_DENIED) and 

     // check call stack
     (AExceptionInfo.CallStack.Count > 0) and 
     (AExceptionInfo.CallStack[0].Location.UnitName = 'ServiceProvider'and
     (AExceptionInfo.CallStack[0].Location.ProcedureName = 'Connect'and

     // check exception address
     (AExceptionInfo.Address = Pointer($00456789)) and 

     // check exception module
     (AExceptionInfo.Module = $00400000) and 

     (AExceptionInfo.Module = HInstance) and 

     // check exception module name
     SameFileName(ExtractFileName(AExceptionInfo.ModuleName), 'Project1.exe'and 

     // check exception thread
     (AExceptionInfo.ThreadID = MainThreadID) and 

     // check for known BugID
     (AExceptionInfo.BugID = $E36F0000) and 

     // check for handler (what hook has catched the exception)
     (AExceptionInfo.Handler = atVCL) and 

     // check for misc. props
     (not AExceptionInfo.Handled) and 
     AExceptionInfo.SafeCallExpt and
     AExceptionInfo.ThreadException
     AExceptionInfo.InitializationException then
  begin
    // ...
    Exit;
  end;
end;

 

 

Option 4: if you need to override message for a specific location rather than exception itself - then you can wrap the target code in a construct like this:

 

uses
  EExceptionManager, // for ExceptionManager
  EException,        // TEurekaExceptionInfo
 
var
  EI: TEurekaExceptionInfo;
begin
  try
    // ... your actual code here ...
  except
    on E: Exception do
    begin
      // Obtain EurekaLog's exception info
      EI := ExceptionManager.Info(E);
      // It could be nil if EurekaLog is disabled
      // or when EurekaLog is instructed to ignore this exception
      if Assigned(EI) then
      begin
        // Override exception message
        EI.AdditionalInfo := 'Sorry, there was a problem';
        // Tells EurekaLog to use the .AdditionalInfo property instead of real message
        EI.Options.UseExceptionComments := True;
      end;
 
      // Continue unwinding
      raise;
    end;
  end;
end;

 

See also: how to get exception info?

 

 


 

2. Replacing the message

 

Replacing exception message will replace the exception message itself. Both bug report and dialog will show the same changed message. This is typically used if you need to update the exception by adding additional information. In other words, both EurekaLog and exception object will use the same message.

 

Replace exception message for a specific exception

You can use the SetExceptionMessage function:

 

uses
  EBase; // for SetExceptionMessage
 
  try
    // ... your actual code here ...
  except
    on E: Exception do
    begin
      // Changes both E.Message and EurekaLog's exception info
      SetExceptionMessage(E,
        Format('Error Opening File "%s": %s',
        [AFileName, E.Message]));
      // Continue unwinding
      raise;
    end;
  end;

 

 

See also:




Send feedback... Build date: 2022-03-28
Last edited: 2022-01-14
PRIVACY STATEMENT
The documentation team uses the feedback submitted to improve the EurekaLog documentation. We do not use your e-mail address for any other purpose. We will remove your e-mail address from our system after the issue you are reporting has been resolved. While we are working to resolve this issue, we may send you an e-mail message to request more information about your feedback. After the issues have been addressed, we may send you an email message to let you know that your feedback has been addressed.


Permanent link to this article: https://www.eurekalog.com/help/eurekalog/how_to_override_exception_message.php