EurekaLog's options are not something your program reads at startup from a file next to the
executable. They are decided while the project is built: they live in an .eof settings file, the
build's post-processing step loads them and adds them to the executable, and from then on they are
part of the binary. What a developer can do with them afterwards is narrower than it looks - read
them, change a documented subset of them at run time, and read back custom keys of your own - and
knowing which file a given build actually used is often the whole answer to "why did it behave
differently on the build machine".
If IDE and build-machine executables behave differently, follow the file-selection rules in section 25.3 before changing runtime code. If you want reproducible shared settings, use section 25.4; if project files must stay read-only, use section 25.6. Chapter 2 connects these choices to compiler prerequisites, post-processing and deployment. Chapter 1 provides the first-report walkthrough.
25.1 Where the options live
EurekaLog options are stored in a UTF-8 text file in INI format, under [Exception Log].
For example, this deliberately short file changes one tooling option and adds an application key;
it is not a complete enabled-project configuration:
[Exception Log]
DeleteMapAfterCompile=0
Custom_ReportLabel="Desktop"
Several facts about that file matter in practice:
- The file that belongs to a project is named after the project. EurekaLog stores the project's
base settings in an
.eoffile with the same name as the project file: aProject1.dprgets aProject1.eof. That file is used by default in all cases - compiling from the IDE and compiling from the command line alike. - Base settings are a delta. When EurekaLog saves the base settings of a project it writes only
the options whose values differ from the defaults. It writes the full set of options only when
you export options to external settings. So a hand-edited
Project1.eofis a list of departures from the defaults, not a complete picture of what the executable will do. - Some options never leave the IDE. Options whose names start with
_are not saved into the executable: they are design-time only, stored in the project options but not injected into the final binary. They are the settings you use to steer the tooling, not the running program. - Some options are only for the tooling in another sense: the
DoNotTouchfamily described in section 25.6, which tells EurekaLog how much it is allowed to modify in your project.
.eof files are just renamed text ini-files, and they can be obtained in several ways: by using the
"Export" button in the project options dialog, by saving settings to a new file in the external
settings editor, by creating and editing one manually in any text editor, or by copying another
.eof file. When you export, EurekaLog writes the complete set of options, which is what makes an
exported file useful as a profile you can re-import as a starting point.
Exported profiles have a default home: %AppData%\Neos Eureka S.r.l\EurekaLog\Profiles\ (for
example C:\Users\UserName\AppData\Roaming\Neos Eureka S.r.l\EurekaLog\Profiles). Any .eof file
placed there appears as a "custom" project type in EurekaLog's project-type list; .eof files
outside that location do not appear there at all. Apart from that folder, a typical place to keep an
external .eof is the project's own folder or a sub-folder of it. That freedom belongs to external
files, which are named explicitly; the per-build configuration files of section 25.3 have to sit in the same
folder as the project file.
Use the project options or standalone settings editor for ordinary changes. Reserve manual edits
for custom keys and settings with no UI, such as DoNotTouch. Export a configured project rather
than trying to build a complete enabled configuration by guessing keys and numeric enum values.
25.2 The syntax of a settings file
The rules the documentation gives for a settings file are short but complete, and they are what you need if you generate or parse one:
- Each option has the form
Name=Value. - Each option occupies a single line only; line breaks inside text parameters are allowed through encoding.
- Integer values are stored directly.
- Boolean values are stored as
0(False) or1(True). - Float values are stored as fixed-point values, and the decimal delimiter is always
.- for example12.345. - Enumeration values are stored as integers, not as text.
- String values are enclosed in double quotes, which is what allows spaces and line breaks inside
them. An empty string may be stored as two double quotes (
"") or as an empty parameter.
Inside strings, four characters need escaping, and non-ASCII text has a recommended encoding:
\q a double quote character ("), inside a quoted string
\r\n a line break
\\ a backslash character
%% a percent character
%U<hex> a Unicode character, e.g. %U044F for #$44F (Cyrillic small letter Ya)
While non-ASCII symbols can be stored "as is", the documentation strongly recommends encoding them
as %U<hex-code>.
Three more rules that are easy to get wrong:
- Sort order is a convenience, not a requirement. Options are sorted in the files EurekaLog writes, but new options can be entered and placed in any order, and there is no need to preserve the sort order.
- There is no predefined list of allowed option names. The file is a key/value store as far as the syntax is concerned.
- There is a reserved convention for your own keys. Use a
Custom_(orMy_) prefix: EurekaLog will never have an option name starting withCustom_, so your names cannot collide with its settings.
Read your custom keys with CurrentEurekaLogOptions:
uses
EBase, EModules;
function ReportLabel: String;
begin
Result := '';
if IsEurekaLogActive then
Result := CurrentEurekaLogOptions.CustomField['Custom_ReportLabel'];
end;
This function belongs in the reporting executable or standalone module, not a lightweight DLL.
Use CurrentEurekaLogOptions, declared in EModules; do not substitute the spelling
CurrentEurekaModuleOptions.
25.3 Which file a build actually uses
There is a documented resolution order, and it is the part of this chapter you are most likely to need when two builds of "the same" project behave differently.
- Base settings.
<ProjectName>.eofnext to the project file -Project1.eofforProject1.dpr. Used by default in all cases. - Per-build-configuration settings. You may create individual settings for each build
configuration, and the expected naming convention is
<ProjectName>_<BuildConfigurationName>.eof. ForProject1.dpr, building in the "Debug" build configuration makes EurekaLog useProject1_Debug.eof; switching to "Release" and building again makes it useProject1_Release.eof. - Fallback. If the specific configuration file does not exist for the current build
configuration, EurekaLog falls back to the base settings in
<ProjectName>.eof.
The documented way to produce a per-configuration file is to configure EurekaLog for that
configuration, save it with Export into <ProjectName>_<BuildConfigurationName>.eof in the
project's folder, and then close the dialog with Cancel instead of OK: saving would write
those temporary changes into the project's own .eof and turn them into the base settings. If you
did not create a file for some configuration, the base settings have to be checked afterwards.
Two rules qualify that sequence:
- There is no inheritance support in EurekaLog's settings. A
Project1_Debug.eofis not a patch applied on top ofProject1.eof: it is the whole settings file for that build. The fallback in step 3 is all-or-nothing. (The documentation states this flatly in more than one place, including for project groups.) - A full rebuild is required after switching the active build configuration - not just a compile. For a change of target platform the same advice is given as a recommendation rather than a requirement.
When you drive the build yourself, the IDE variables that name the configuration and the platform are
the documented way to pick the right file, since they expand to the build configuration name
(such as Debug and Release) and to the short platform name (such as Win32, Win64, OSX). A
file name like Project1_Win32_Debug.eof can therefore be selected with a switch such as
--el_config=Project1_$(Platform)_$(Config).eof.
The symbol that decides whether anything happens at all
Before any of that file resolution matters, post-processing checks one thing: whether the EUREKALOG
conditional symbol is defined in the project. EurekaLog's own units are included in the program's
uses clause under that symbol - the documented example guards EMemLeaks, EResLeaks, the dialogs,
EDebugExports, EFixSafeCallException, EMapWin32, EAppVCL and ExceptionLog7 with {$IFDEF EUREKALOG}. If the symbol is not defined, post-processing is skipped.
Do not remove EUREKALOG_VER7 - only EUREKALOG. And mind whose inheritance is whose: build
configuration settings in the IDE are inherited, so a symbol enabled in the "Base" configuration
reaches every configuration below it. Where EurekaLog is wanted in some configurations and not in
others, the documented procedure is to remove EUREKALOG from the base configuration first and then
enable it in the specific configurations you want, enabling EurekaLog only on "leaf" configurations,
or to disable the inheritance for the symbol manually. If you build with a configuration in which the
symbol is not defined, EurekaLog detects that and notifies you - either switch to a configuration
that has it, or define the symbol for the current one.
This, then, is the difference between the two kinds of "inheritance" you meet here: the symbol is inherited through the IDE's build configurations like any other define; the settings are not inherited at all.
25.4 External settings, and sharing them
Sometimes the settings should not live next to the project. The documented reasons: sharing common
settings between several projects, or having no Delphi/C++ Builder project at all - for example when
you need EurekaLog settings for a DLL built by another compiler. That is what external settings are:
a standalone .eof file referenced from the project instead of the project's own.
How the reference is made, in the order the documentation presents the methods:
- From the project options: the path is specified as relative to the project's folder. The
.eoffile name can be arbitrary - it need not match the project's name, and it need not sit in the same folder. - From the command-line compiler, with the
--el_configswitch. Note the interaction the documentation points out:ecc32/ecc32speedrespect the "use external settings" option recorded in the project, so specifying the file once in the project options is enough; you can still pass--el_configyourself if you want to. - Without the IDE expert installed, you can still work: no post-processing happens from the IDE,
but the project's own
.eoffile is left untouched rather than deleted, so you can edit it with the external settings editor or a plain text editor, and it will be used automatically if you make manual post-processing.
Taking control of the pre-build and post-build steps
First establish a working report using chapter 1, then export the working options to a separately
named file such as Project1_Custom_Config.eof. Add DoNotTouch=1 to the project's own
options on Advanced / Custom/Manual and save; do not add it to that exported configuration.
You now own the integration that the IDE expert previously maintained.
For an IDE/MSBuild build, enter this as the pre-build event, on one physical line:
"C:\Tools\EurekaLog\Packages\Studio16\ecc32.exe" "--el_prepare=$(PROJECTPATH)" "--el_config=Project1_Custom_Config.eof"
Enter this as the post-build event, after successful compilation, also on one physical line:
"C:\Tools\EurekaLog\Packages\Studio16\ecc32.exe" "--el_alter_exe=$(PROJECTPATH);$(OUTPUTPATH)" "--el_config=Project1_Custom_Config.eof"
Replace C:\Tools\EurekaLog with the installation directory and Studio16 with the package
directory matching the IDE that builds this project; it is an example, not a universal compiler.
Use the IDE mapping and tool selection in chapter 2. Replace the configuration filename with
your exported file. Keep the quoted switches intact: the semicolon separates the project path
from the actual output executable path. $(OUTPUTPATH) matters when configurations or
platforms have different output directories. Do not replace it with a guessed project-root EXE.
Do not prefix these commands with IF EXIST: a missing postprocessor must be a build failure,
not a silently unprocessed release. Make the build fail on a nonzero event exit code. Inspect the
build output for both commands and the completed post-processing stage, not just the Delphi
compiler's success.
--el_prepare handles required units, but you must set the required compiler/debug-information
options yourself for every enabled configuration (chapter 2). Ensure the events are inherited
by, and not overridden in, each applicable configuration. For per-platform files you can use
"--el_config=Project1_$(Platform)_$(Config).eof" in both commands.
These are IDE/MSBuild events: invoking dcc32 directly does not run them. A direct-compiler
script must perform preparation and post-processing explicitly, or use the EurekaLog command-line
build route in chapter 2. Rebuild and exercise the produced executable for each supported
configuration; a successful compile alone does not establish that it contains the intended settings.
Sharing inside a project group: two options, one conclusion
EurekaLog offers two documented ways to give a group of projects the same settings, and they differ in whether later changes propagate.
- By value. Configure one project, then import its
.eofinto every other project of the logical group (or copyProject1.eofoverProject2.eofand so on). All the projects end up with exactly the same settings, but they are isolated: a later change in one project does not affect the others, and to change the group you must edit one project and repeat the exercise. - By reference. Configure one project as the master, save its settings to an
.eof, and switch "Use external settings" on in every other project of the group, pointing at that file. All projects now read the common file, so editing the master's options adjusts the whole group. The documented price is that the.eoffiles must not be deleted - they are required. A project that should differ from the group is taken out of the arrangement by unchecking "Use external settings", importing the.eof, and adjusting it locally. The documented shortcut is to set up "Use external settings" in one project and copy that project's.eof- the file that carries the reference - to the others; it works only when all of the projects are in the same folder.
Both procedures come with the same design advice: sharing settings blindly between projects is not a good idea, because projects of different types - VCL application, DLL, packages, service - need slightly or significantly different settings. Group your projects logically (one group for the main executable, one for DLLs, one for packages), and create one settings file per type. The same advice appears for external settings: using the same settings for different project types is usually not a good idea; if you want to copy settings between projects, use import/export.
And the conclusion that matters when you are debugging a settings puzzle: there is no inheritance.
When the resolution goes wrong
Three documented failure modes, all worth remembering because they look like EurekaLog misbehaving when they are really a settings file being wrong:
- Batch builds and external build tools. The warnings in these articles repeat one sentence: be
extra careful when doing batch compilation of projects in project groups or when using external
build tools, because IDE bugs and other issues may pass incorrect information to EurekaLog (via the
OpenTools API, in the IDE's case). Pay close attention to which settings file the build tool hands
to the compilers, and double-check the final executables. A per-configuration
.eofthat was never picked up, or the wrong one being picked up, is exactly the kind of thing this warning is about. - Removing and re-adding EurekaLog to the project. The documentation calls this out as a wrong
way to switch EurekaLog off for a build: the reset removes EurekaLog from the project, and in doing
so erases all of its existing options, so the next "add" starts from the defaults. If the project's
options were customised at all, they are lost. Use the
EUREKALOGsymbol or run-time switching instead. - Read-only project files. Setting
.dpr/.dprojto read-only - a common marker for version control - prevents EurekaLog from working properly, because it needs to modify the project to include its units and to adjust options. Worth knowing: EurekaLog only tries to modify your project files when the project does not match its configuration (map file generation disabled,usesclause missing the EurekaLog units, and so on); if there is no need to change anything it will not write. That is why a "file is read-only" error is a useful signal in itself: the configuration changed and the project needs adjusting.
25.5 What can be changed at run time
Everything above is build-time. At run time the documentation offers these levers, and it makes the cost of using them plain: run-time customisation still pays the compilation and startup penalty of having EurekaLog in the build. If performance is the reason you are switching things off, turning them off at run time does not remove that cost.
For example, a diagnostic launch mode may disable EurekaLog at startup:
uses
SysUtils, EBase;
procedure ConfigureDiagnosticLaunch;
begin
if FindCmdLineSwitch('disable-reporting', True) then
SetEurekaLogState(False);
end;
Call this once after startup has selected the launch mode and before starting normal work.
Treat this switch as an application policy decision: it prevents reporting while disabled.
SetEurekaLogState, declared in EBase, returns the previous global state. When temporarily
changing the state, save that return value and restore it in a finally block instead of
unconditionally enabling reporting. SetEurekaLogStateInThread is the per-thread control;
IsEurekaLogActive reports the global state (chapter 10).
Note the asymmetry with the build-time approach: switching the symbol off removes the code and its
cost, switching EurekaLog off at run time does not.
To change just the reporting destination, dialog, saving or sending policy, change the live options at startup. Section 17.3 gives the service/GUI setup, including the feature-in-build prerequisites. For a local diagnostic build that must save reports without sending them:
uses
EBase, ETypes, EModules;
procedure KeepReportsLocal;
begin
if not IsEurekaLogActive then
Exit;
CurrentEurekaLogOptions.SaveLogFile := True;
CurrentEurekaLogOptions.SenderClasses := esmNoSend;
end;
The configured output folder still needs to be writable by the process account. This changes
defaults for future exceptions, not already-raised ones; use the current exception's
Options inside an event handler (section 17.4 and section 24.3). Sender destination setup and real-send
verification are in chapter 3. Memory and leak control use EMemLeaks rather than these
properties (chapter 12).
If performance is the reason for changing settings, measure the enabled features rather than disabling the entire extended memory manager by reflex. Allocation stack collection for leak tracking can be a substantial cost. A documented configuration to try is to keep Enable extended memory manager enabled while disabling Catch memory leaks and, if appropriate, other memory-debugging features. This is not a universal performance guarantee: workload, bitness and enabled checks matter (chapters 22 and 5).
The distinction has a correctness consequence too: EurekaLog uses its memory-manager filter to track exception-object lifetimes. In the documented worst case, Delphi 2007 or earlier with both the extended memory manager and low-level hooks disabled cannot track those lifetimes.
For the question "is EurekaLog present in this build at all?", the documentation points at one unit
as the deliberate answer: the EBase unit is described as specially designed to be included in any
application without including the full EurekaLog code, and as the way to test whether EurekaLog was
enabled for your application. Its answer is a run-time one - IsEurekaLogInstalled - with the
{$IFDEF EUREKALOG} conditional of section 25.3 as the compilation-time alternative.
25.6 Leaving the project alone: the DoNotTouch family
The settings file also carries the switches that decide how much EurekaLog is allowed to modify your
project. They are ordinary options, written under [Exception Log]. The trio that keeps automatic
post-processing going while EurekaLog leaves the project files alone is DoNotTouchOptions,
DoNotTouchUnits and DoNotTouchPackages; DoNotTouch disables all EurekaLog assist for the project,
and DoNotTouchCompilation disables the post-processing assist:
| Option | Documented effect |
|---|---|
DoNotTouch |
Completely disables EurekaLog assist for the project. |
DoNotTouchCompilation |
Disables post-processing assist. Documented for when you intend to invoke ecc32/ecc32speed manually. |
DoNotTouchOptions |
Disables modification of project options and defines. For when you manage project options manually. |
DoNotTouchUnits |
Disables modification of units in the uses clause. For when you manage your units manually. |
DoNotTouchPackages |
Disables modifications in the run-time packages list. |
The documented use for the whole family is an initial setup followed by a lock-down:
- Configure EurekaLog in the project once, with the project files writable. This step sets the project options, includes the EurekaLog units in the application, and stores EurekaLog's options with the project.
- Turn the assist off -
DoNotTouchOptions=1,DoNotTouchUnits=1,DoNotTouchPackages=1- and save. EurekaLog will no longer try to modify project options or the list of units. - Restore the read-only attribute on the project files. The project can be read-only and EurekaLog works; it post-processes the project on each compilation using the currently set options.
The options are entered as plain lines in the [Exception Log] section:
[Exception Log]
DoNotTouchOptions=1
DoNotTouchUnits=1
DoNotTouchPackages=1
The same mechanism has an inverted use. If you keep EurekaLog's IDE expert installed but have
non-EurekaLog projects whose files are read-only, EurekaLog may try to remove itself from them and
fail because the files cannot be written. The documented fix is to create an empty .eof text file
with the same name as the project, containing:
[Exception Log]
DoNotTouch=1
Save it, and the project is skipped.
25.7 The units that expose the configuration
Chapter 17 supplies the callable contracts and examples for these units; appendices A and D provide the lookup reference. Use this section to choose the right layer, not as a list of statements to paste into your program.
EConfig - the configuration storage
EConfig is the layer that reads and writes EurekaLog's configuration and knows whether that
configuration lives in the registry or in an .ini file. By default it is the registry, under the
general EurekaLog key (\Software\EurekaLab\EurekaLog\7.0); SetupConfig(AUseRegistry, AKeyPathOrFileName) changes that, and it is meant to be called once at application startup, preferably
in a unit's initialization section. The typed readers are wrappers around ConfigReadString, and the
typed writers around ConfigWriteString, so the string routines carry the real work.
// location and identity of the configuration store
ConfigFileName // returns .ini-file name to store EurekaLog configuration
ConfigIsRegistry // indicates if EurekaLog configuration is stored in the registry or in .ini-file
ConfigKeyPath // returns registry key name to store EurekaLog configuration
SetupConfig // changes EurekaLog configuration storage
// typed access to a key in a section
ConfigReadBool // reads boolean value from specified key and section
ConfigReadFloat // reads float value from specified key and section
ConfigReadInteger // reads integer value from specified key and section
ConfigReadString // reads string value from specified key and section
ConfigWriteBool // writes boolean value to specified key and section
ConfigWriteFloat // writes float value to specified key and section
ConfigWriteInteger // writes integer value to specified key and section
ConfigWriteString // writes string value to specified key and section
ConfigDelete // deletes a key from the specified section
// encoding of values in the store
EncodeConfigValue // low-level routine to encode data before saving to configuration storage
DecodeConfigValue // low-level routine to decode data after reading from configuration storage
// raw access to the two backing stores
IniReadString // reads string from .ini file
IniWriteString // writes string to .ini file
RegKeyCheck // checks registry key for existing
RegKeyRead // reads string from registry key
RegKeyWrite // writes string to registry key
ReadRawStrings // backward-compatibility routine for the raw store
WriteRawStrings // backward-compatibility routine for the raw store
The pair EncodeConfigValue/DecodeConfigValue is the code-side counterpart of the escaping rules in
section 25.2: it escapes the special characters a value contains before it is stored - the documentation names
#0, line breaks and trailing spaces - and reverses that on the way back, with the exact encoded form
left unspecified. The typed writers already perform that encoding, so this pair is there for
implementing your own high-level wrapper; use the type specific readers (ConfigReadBool and friends)
rather than the raw ones unless you are working with the store as text.
EModules - options and module facts
| Need | Routine |
|---|---|
| Change defaults for future exceptions in the current reporting module | CurrentEurekaLogOptions |
| Describe the executable | GetApplicationName, GetApplicationDescription |
| Identify the module containing an exception address | GetExceptionModuleName, GetExceptionModuleVersion |
| Obtain the module's post-processing/compilation time | GetCompilationDate, GetCurrentModuleCompilationDate |
| Format the project's compilation date or time as text | __DATE__, __TIME__ |
Call the options accessor only when EurekaLog is active; an invalid call displays an error and terminates the process. The module-information routines are a different group: they can be useful without an active tracer. Their empty-result and date-fallback rules are in section 17.6.