Root > Basic procedures > Configuring project itself > Logging additional exception information

Logging additional exception information

Previous pageReturn to chapter overviewNext page   

EurekaLog creates bug reports for each unhandled exception in your app. For example (a part of bug report is shown):

 

Exception:

-------------------------------------------------------------------------------------------------------------------------------

 2.1 Date          : Sat, 11 Apr 2026 15:51:09 +0300

 2.2 Address       : 012AB618

 2.3 Module Name   : Project1.exe

 2.4 Module Version: 1.0.0.0

 2.5 Type          : EAccessViolation

 2.6 Message       : Access violation at address 012AB618 in module 'Project1.exe' (offset A9B618). Write of address 00000000.

 2.7 ID            : 73BA1063

 

EurekaLog captures type (class) of the exception object and its message. However, some exception classes may have additional information. For example:

 

type
  EOleException = class(EOleSysError)
  private
    FSource: string;
    FHelpFile: string;
  public
    constructor Create(const Messagestring; ErrorCode: HRESULT;
      const Source, HelpFile: string; HelpContext: Integer);
    property HelpFile: string read FHelpFile write FHelpFile;
    property Source: string read FSource write FSource;
  end;

 

The EOleException class has the additional HelpFile and Source properties, and its ancestor (the EOleSysError class) also has an additional ErrorCode property.

 

Historically, EurekaLog only saves the exception class and its message to bug reports. This is because EurekaLog doesn't know about other exception classes, as other exception classes are defined in units other than System.SysUtils. For example, the EOleException class is defined in the System.Win.ComObj unit. Referencing this unit directly (so EurekaLog could reference the EOleException class) would mean that every application running EurekaLog would carry COM code.

 

The same is true for other classes: EUpdateError (defined in the Data.DB unit), EZipFileNotFoundException (defined in the System.Zip unit), ESocketError (defined in the System.Net.Socket unit), EJSONException (defined in the System.JSON unit), DOMException (defined in the Xml.xmldom unit), EXMLException (defined in the Xml.Internal.OmniXML unit), ERemotableException (defined in the Soap.InvokeRegistry unit), ERequestError (defined in the REST.Types unit), and so on - you get the idea: you definitely don't want to include all these units in your practically empty application if you're just adding EurekaLog to it.

 

 

Logging additional exception properties

EurekaLog has the \Source\Extras\EExtraExceptionInfo.pas unit, which is added to each project with EurekaLog by default. Once the EExtraExceptionInfo unit is added to your project - it will register a callback which will save additional properties of known exception classes into bug reports produced by EurekaLog:

 

Exception:

-----------------------------------------------------

 2.1 Date          : Sat, 11 Apr 2026 20:35:48 +0300

 2.2 Address       : 0137F5D9

 2.3 Module Name   : Project1.exe

 2.4 Module Version: 1.0.0.0

 2.5 Type          : EOleException

 2.6 Message       : Catastrophic failure.

 2.7 ID            : 2EBFEC43

 

Custom Information:

---------------------------------------

 9.1 EOleSysError.ErrorCode: $8000FFFF

 

 

Customization

There is a catch though. The EExtraExceptionInfo unit knows only about exceptions from the System.SysUtils unit by default. If your project uses other units (such as System.Win.ComObj for the EOleSysError exception class from the example above) - these has to be enabled explicitly. The way to do this is to use conditional defines:

Open your project in IDE;
Go to IDE's "Project" / "View source". This will open your project (.dpr) file in IDE's editor;
You should see the list of EurekaLog units being included into your project. Find the EExtraExceptionInfo unit, place cursor on it;
Press Ctrl + Enter, or right click with the mouse and select the "Open File At Cursor" command.

This will open the EExtraExceptionInfo.pas file in IDE's editor.

 

The beginning of the EExtraExceptionInfo.pas file has a detailed description of all exception classes which it supports:

 

...
//
// Select/add option(s) for exception classes which are used in your app:
//
 
// [System.Win.ComObj] EOleSysError, EOleException
// {$DEFINE E_SYSTEM_WIN_COM_INFO}
 
// DEPRECATED [Vcl.OleAuto] EOleSysError, EOleException (Delphi 6+)
// {$DEFINE E_VCL_OLEAUTO_INFO}
 
// [Data.DB] EUpdateError
// {$DEFINE E_DATA_DB_INFO}
 
// [System.Zip] EZipFileNotFoundException
// {$DEFINE E_SYSTEM_ZIP_INFO}
...

 

You can browse this list and find units which are being used in your project. For example, if your project references the System.Win.ComObj unit - you would need the E_SYSTEM_WIN_COM_INFO symbol. If your project references the Data.DB unit - you would need the E_DATA_DB_INFO symbol. And so on.

 

Tip: if you don't know what units are being used in your project - use the "Start" / "Programs" / "EurekaLog" / "Tools" / "PE Analyzer" tool to look what is inside your compiled executable file.

 

Once you have learned the names of all the symbols you need - go to project's options (use IDE's "Project" / "Options" menu item). Then open conditional defines settings. These can be located in various places - depending on your IDE and personality. For example, it is located on the "Building" / "Delphi compiler" tab for modern Delphi:

 

 

Add all symbol names which you learned on the previous step. We recommend to add symbol names either to the "All configuration" target or to the platform-specific target. Adding a symbol name will uncomment code in the EExtraExceptionInfo unit, which will include the corresponding unit and extract additional info. Like so:

 

uses
  {$IFDEF E_SYSTEM_WIN_COM_INFO}ComObj,{$ENDIF}
   
...
 
  {$IFDEF E_SYSTEM_WIN_COM_INFO}
  if E is ComObj.EOleSysError then
  begin
    Fields.Values['EOleSysError.ErrorCode']   := '$' + IntToHex(ComObj.EOleSysError(E).ErrorCode, 8);
    if E is ComObj.EOleException then
    begin
      Fields.Values['EOleException.Source']   := ComObj.EOleException(E).Source;
      Fields.Values['EOleException.HelpFile'] := ComObj.EOleException(E).HelpFile;
    end;
  end;
  {$ENDIF}

 

That is why the EExtraExceptionInfo unit is placed as source code (.pas) file into the \Source\Extras\ folder: so it can be recompiled from the source code when conditional defines change - unlike regular EurekaLog units which come precompiled and never change.

 

IMPORTANT NOTE: do not forget to make a full build of your project (not just compile) after changing the conditional defines option.

 

 

Using EExtraExceptionInfo with your own callbacks

The EExtraExceptionInfo unit adds exception information into the "Custom information" section of your bug reports. However, you may also add your own custom information. For example:

 

procedure AddMyData(const ACustom: Pointer;
  AExceptionInfo: TEurekaExceptionInfo; ALogBuilder: TBaseLogBuilder;
  ADataFields: TStrings; var ACallNextHandler: Boolean);
begin
  // Your own code here. Code below is just an arbitrary example
  ADataFields.Values['License'] := GetUserLicense;
  ADataFields.Values['User']    := GetUserName;
  ADataFields.Values['Build']   := '3.5';
end;
 
initialization

  // Ask EurekaLog to call your code when a bug report is composed
  RegisterEventCustomDataRequest(nil, AddMyData);
end.

 

How will your own event handler play with EurekaLog's EExtraExceptionInfo unit?

 

RegisterEvent* functions add event handlers into lists. EurekaLog would call each registered handler from a list until there are no more handlers or some handler would return ACallNextHandler = False. So, if you register your own OnCustomData event handler - it will be called together with the EExtraExceptionInfo unit, producing the following output (see code examples above):

 

Exception:

-----------------------------------------------------

 2.1 Date          : Sat, 11 Apr 2026 20:35:48 +0300

 2.2 Address       : 0137F5D9

 2.3 Module Name   : Project1.exe

 2.4 Module Version: 1.0.0.0

 2.5 Type          : EOleException

 2.6 Message       : Catastrophic failure.

 2.7 ID            : 2EBFEC43

 

Custom Information:

-------------------------------------------------

 9.1 EOleSysError.ErrorCode: $8000FFFF

 9.2 License               : kjlasdioj234879asd

 9.3 User                  : example@example.com

 9.4 Build                 : 3.5

 

Here: the 9.1 line is produced by the EExtraExceptionInfo unit, while the 9.2-9.4 lines are produced by your code (event handler).

 

The last argument for any RegisterEvent* function (named AFirst) defines if the function should add your handler to the beginning of the list (AFirst = True) or to the end (AFirst = False; default). For example, registering your handler like so:

 

initialization
  RegisterEventCustomDataRequest(nil, AddMyData, True { - added });
end.

 

will produce the following output:

 

Exception:

-----------------------------------------------------

 2.1 Date          : Sat, 11 Apr 2026 20:35:48 +0300

 2.2 Address       : 0137F5D9

 2.3 Module Name   : Project1.exe

 2.4 Module Version: 1.0.0.0

 2.5 Type          : EOleException

 2.6 Message       : Catastrophic failure.

 2.7 ID            : 2EBFEC43

 

Custom Information:

-------------------------------------------------

 9.1 License               : kJlaSdioj23t879aSd

 9.2 User                  : example@example.com

 9.3 Build                 : 3.5

 9.4 EOleSysError.ErrorCode: $8000FFFF

 

As you can see, now it is your output listed first, followed by the output from the EExtraExceptionInfo unit.

 

And since your handler will be called first (before EExtraExceptionInfo unit) - you can also do something like this:

 

procedure AddMyData(const ACustom: Pointer;
  AExceptionInfo: TEurekaExceptionInfo; ALogBuilder: TBaseLogBuilder;
  ADataFields: TStrings; var ACallNextHandler: Boolean);
begin
  ADataFields.Values['License'] := GetUserLicense;
  ADataFields.Values['User']    := GetUserName;
  ADataFields.Values['Build']   := '3.5';
   
  // Do not call code from EExtraExceptionInfo for the EOleException exceptions 
  if AExceptionInfo.ExceptionClass = EOleException.ClassName then
    ACallNextHandler := False;
end;

 

Additionally, if you don't want to add additional exception properties to the custom information section - you can change this behaviour to adding additional exception properties to exception's message. You need to add the E_ADD_CUSTOM_MESSAGE symbol to conditional defines. Doing so will produce the following output:

 

Exception:

-----------------------------------------------------

  2.1 Date          : Sat, 11 Apr 2026 20:35:48 +0300

  2.2 Address       : 0137F5D9

  2.3 Module Name   : Project1.exe

  2.4 Module Version: 1.0.0.0

  2.5 Type          : EOleException

  2.6 Message       : Catastrophic failure.

                      ErrorCode=$8000FFFF

  2.7 ID            : 2EBFEC43

 

Custom Information:

----------------------------------

  9.1 License: kJlaSdioj23t879aSd

  9.2 User   : example@example.com

  9.3 Build  : 3.5

 

Here: the "ErrorCode" line is added to exception's message by the EExtraExceptionInfo unit with the E_ADD_CUSTOM_MESSAGE option, while "Custom Information" section is composed by your AddMyData OnCustomData event handler from the example above.

 

You may also enable the E_ADD_NO_CUSTOM_INFO option (by adding its symbol's name to conditional defines) to completely disable assist from the EExtraExceptionInfo unit.

 

 

See also:




Send feedback... Build date: 2026-05-27
Last edited: 2026-05-02
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/extra_exception_info