Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: TEventLogger registration


This question is not answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 1 - Last Post: Aug 27, 2014 10:27 AM Last Post By: Remy Lebeau (Te...
Zdravko Donev

Posts: 1
Registered: 9/14/14
TEventLogger registration  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 27, 2014 5:31 AM
Hello,

I want to make a log with errors during the execution of my application. I'm trying to write an event to the windows Event Viewer with a VCL form application with C++ Builder XE5.
I'm using Vcl.SvcMgr.TEventLogger class.

The code in the header file is :
TEventLogger *Event;

The code in the cpp file is :
Event=new TEventLogger("MySource"); 
Event->LogMessage("MyMessage");


But beside my message, in the error description in the Event Viewer there is a message : "The description for Event ID 0 from source MySource cannot be found. Either the component that raises this event is not installed on your local computer or the installation is corrupted.". I've been told to use Message file(.mc) but I haven't found any useful documentation about how to create such file and implement it into my project. How can I remove that description and write only the message that I want? Should I be using other C++ class? I couldn't find any documentation about this class. The idea of using Event Viewer is that when the application is running on an user with restricted rights he won't be able to write to files, meaning I can't just type into a ".txt" file. If anyone else has a different idea how to make a log with errors, please share! Also any information on how to do that with a Firemonkey application with be useful as well. :)

Greetings,
Zdravko
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: TEventLogger registration  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 27, 2014 10:27 AM   in response to: Zdravko Donev in response to: Zdravko Donev
Zdravko wrote:

The code in the header file is :
TEventLogger *Event;

The code in the cpp file is :
Event=new TEventLogger("MySource");
Event->LogMessage("MyMessage");

TEventLogger is meant for TService's internal use in the TService::LogMessage()
method. Since you are not creating a Service project, you should not be
using the SvcMgr unit at all. You can call the Win32 API RegisterEventSource()
and ReportEvent() functions directly instead.

But beside my message, in the error description in the Event Viewer
there is a message : "+The description for Event ID 0 from source
MySource cannot be found. Either the component that raises this
event is not installed on your local computer or the installation is
corrupted+.".

You have to define a MESSAGETABLE in your app's resources, or in the resources
of a DLL, where the table contains your desired log message string(s):

http://msdn.microsoft.com/en-us/library/windows/desktop/aa381027.aspx

Then, you have to register a custom event source in the Event Viewer's Registry
key, and tell it what file your MESSAGETABLE resource is located in:

Event Sources
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363661.aspx

After that, whenever you log a message, you can specify the Category ID and
Event ID of the desired resource string, and the Event Viewer will retreive
that string from your message table, thus removing the "The description for
Event ID 0 from source MySource cannot be found" warning.

I've been told to use Message file(.mc) but I haven't found any useful
documentation about how to create such file and implement it into my
project. How can I remove that description and write only the message
that I want?

That is one way to do it, and the preferred way. However, in order to do
that, you have to use Microsoft's Message Compiler (mc.exe), as C++Builder
does not natively support compiling .MC files:

Message Compiler (MC.exe)
http://msdn.microsoft.com/en-us/library/windows/desktop/aa385638.aspx

The Message Compiler is only available with Visual Studio. And I have had
problems in the past with getting MC's output to work correctly with C++Builder
projects (but that was years ago, things might be better now, I don't know).

For C++Builder, it is possible to manually define a message table using a
normal .RC file, it just cannot be compiled with C++Builder's resource compiler
as it does not support the MESSAGETABLE resource type (however, newer versions
of C++Builder allow you to use Microsoft's resource compiler, so that might
work, I haven't tried it yet).

In my own C++Builder projects, here is what I have had to do:

1. create an .RC file with the desired MESSAGETABLE resource content.

2. use XN Resource Editor to create a .RES file with a MESSAGETABLE resource
in it, or alternatively edit the compiled .EXE/.DLL file to add a MESSAGETABLE
resource directly to it.

3. use Resource Hacker to edit the .RES/.EXE/.DLL file to re-compile the
MESSAGETABLE resource using the content of the .RC file (XN doesn't quite
generate the MESSAGETABLE resource correctly if you use it to fill out the
string entries).

4. (optional) use XN again to edit the MESSAGETABLE resource to strip out
unnecessary "%0" format specifiers and line breaks that RH generated.

The tricky part is defining the string IDs in the MESSAGETABLE resource to
match what MC.EXE would generate. Category Name strings are straight forward,
you just use your Category ID numbers as-is. But Event IDs for log messages
use the same layout as an HRESULT, as defined in winerror.h:

//   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
//   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
//  +---+-+-+-----------------------+-------------------------------+
//  |Sev|C|R|     Facility          |               Code            |
//  +---+-+-+-----------------------+-------------------------------+
//
//  where
//
//      Sev - is the severity code
//
//          00 - Success
//          01 - Informational
//          10 - Warning
//          11 - Error
//
//      C - is the Customer code flag
//
//      R - is a reserved bit
//
//      Facility - is the facility code
//
//      Code - is the facility's status code


Set the Customer flag to 1, the Facility to 0 (FACILITY_NULL), and the Code
to whatever you want (I use incrementing numbers starting at 1). In the
.RC file, the Event IDs that have Severity of WARNING or ERROR are specified
as a twos-compliment negative number. For example, 0xA0000003 (Severity=2,
Customer=1, Facility=0, Code=3) would be -1610612733.

Also, for good measure, I also define a string in the MESSAGETABLE that has
an ID of 0 and a value of "%1" as a catch-all for any log messages that get
logged without a Category ID or Event ID specified.

Should I be using other C++ class?

No.

I couldn't find any documentation about this class.

There isn't any, because it is not meant to be used directly.

The idea of using Event Viewer is that when the application is running on
an user with restricted rights he won't be able to write to files, meaning
I can't just type into a ".txt" file.

Yes, you can. You just have to make sure the file is located in a folder
that a restricted user has access to, such as "%APPDATA%\MyFolder".

Also any information on how to do that with a Firemonkey application
with be useful as well. :)

There is no FireMonkey solution for cross-platform event reporting. You
would have to use the Win32 API directly.

--
Remy Lebeau (TeamB)
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02