Click here to Skip to main content
Click here to Skip to main content

Event Logging, Part I: XEventLog - Basic NT Event Logging

By , 22 Apr 2003
 

Introduction

The use of NT event logging is very familiar to those working on NT-based (Win2000, XP) client/server systems. Since this article is classified as beginner, here is the idea behind NT event logging: prior to NT. If an application coder wanted to record errors and events, it would be necessary to create some proprietary error log format as well as logging mechanism (API). These proprietary error logs would also need proprietary UI viewer app as well. Things rapidly get worse when different in-house and third-party apps all write their own error logs - you have to check each log (that is, if you know where to find it).

OK, now comes NT. (Note - some of this info taken directly from MSDN). NT event logging provides a standard, centralized way for applications (and operating system) to record important software and hardware events. The event-logging service stores events from various sources in a single collection called an event log. There are three pre-defined logs that you can view with NT Event Viewer: Application, Security, and System logs. The NT Event Viewer enables you to view and manage logs; and its API enables you to write and examine logs. The Application log contains events reported by user-mode applications, and is the log that your application will write to. By the way, if it isn't clear yet, let me state that NT event logs are not available on Win9x.

As an example, open Event Viewer now: go to Settings | Control Panel | Administrative Tools | Event Viewer. Click on Application in left pane to view its events. The last event logged will be displayed at the top of the list.

        XEventLog demo screenshot

Right-click on Application in left pane, then choose Properties. You will see Application Properties dialog, which allows you to specify location, maximum log size, and filters. Note also Clear Log button on dialog, which you may want to use to clear Application log before starting a debug session. (You can clear the Application log now if you want.)

        XEventLog demo screenshot

A few other things to note about NT Event Viewer user interface: when you left-click Application in left pane, the menus and also toolbar buttons change. For example, you will now see Refresh toolbar button, which is necessary to use if you want to view recent log additions (most developers just leave NT Event Viewer open, and hit Refresh button to view new entries). The NT Event Viewer has many other features, such as exporting log file to an external file. See Event Viewer help, or MSDN topics, for more details.

Now for meat: When you double-click an event in right pane, NT Event Viewer opens Event Properties dialog that shows details about event as well as full message text. Now, leave Event Viewer open, and start XEventLogTest demo app. You will see this:

        XEventLog demo screenshot

Just use default settings, and click Write Log. In Event Viewer, click Refresh button, and new events will appear in list (note: Error event illustrates how to do multi-line strings in event log, see below for details):

        XEventLog demo screenshot

Double-click Information event, and you will see:

        XEventLog demo screenshot

Wait a minute! Where does all this stuff in Description box come from? Well, you've just seen the  number 1 problem in writing to the NT event log: before you can write events to log, you must first create a message file (typically, message file is resource-only DLL). Here is what this means: In the Microsoft view of things, you are expected to store strings for your app in a message DLL. This message DLL encapsulates the output of Microsoft's Message Compiler (mc). In order to log a message, the app must specify the file path of this message DLL - Microsoft calls this "registering an event source". You register this event source in the usual Microsoft manner - by writing directly to the registry (HKLM). You can use Regedit to see the registry keys that XEventLog creates:

        XEventLog demo screenshot

You can then call an event logger API (RegisterEventSource()) to get an event source handle, and finally you use this handle to write to event log with another event logger API (ReportEvent()).

Whew! OK, we have logged an event. Now, this is the part about event logging that is really non-obvious (at least it was to me). The ReportEvent() API has no interaction whatsoever with the message DLL. It is only when you use NT Event Viewer that the message DLL will be loaded, and its compiled messages used. If the Event Viewer can't find message DLL, you get garbage that you see in the above screenshot. If you put message DLL in proper location, Event Viewer will no longer show garbage.

Now let me jump ahead to show you what happens when message DLL is properly registered, and Event Viewer can find it at the location that you specified in registry:

        XEventLog demo screenshot

Now you can easily see the message you logged. And here is the incredible thing: it is very easy to do this, with just one DLL - XEventMessage.dll - that you can reuse unchanged in all your projects. Plus, you don't even have to link to this DLL - it just has to be in your exe's directory, or in some common shared directory. Add two files to your project, and you're ready to log some events. Forget about all that Message Compiler stuff you've read about. No screwy syntax to figure out, no need to transfer all your message strings to some .mc file. It's really this easy! - I even give you XEventMessage.dll to drop into your exe directory (I give you source for it too, if you really like to compile stuff).

But what about parameters, like printf() uses? Doesn't Message Compiler support multiple strings? Yes, it does, but you have to decide whether you want to keep going back and forth between your app and tweaking the message DLL. What if you want three strings? four? five? It is much simpler to do the message formatting in the app (say, with CString's Format() method, that you already know) than to update separate DLL.

Here is example code to log formatted multiple-line values:

    DWORD dwThreadId = 0xDEADBEEF;
    CString str;
    str.Format("Thread=%08X\r\n"
               "Error=%s\r\n"
               "Cause=%s",
               dwThreadId, "Can't delete file", "File does not exist");
    m_pEventLog->Write(EVENTLOG_ERROR_TYPE, str);

and here is what multi-line log event looks like:

        XEventLog demo screenshot

So, while Microsoft documentation would lead you to think that it is necessary for each app to have its own message DLL (and I haven't even mentioned category DLLs or parameter DLLs!), in real world, very few apps do this. It is difficult enough just keeping app up-to-date, let alone DLL too. Today, most apps just pull strings from string resources. To sum up, the Message Compiler may be necessary in some situations, but my goal here is to provide a minimalist drop-in message DLL that is suitable for any app running in production environment. In effect, the message DLL that I present here is simply a pass-thru DLL that is independent of any particular app, and so can be used by many different apps without change.

How To Use

To integrate CXEventLog class into your app, you first need to add following files to your project:

  • XEventLog.cpp
  • XEventLog.h
Also remember to copy XEventMessage.dll to the exe's directory. If you want to test both Debug and Release versions of app, XEventMessage.dll must be in both directories.

If you include XEventLog in project that uses precompiled headers, you must change C/C++ Precompiled Headers settings to Not using precompiled headers for XEventLog.cpp.

Next, include the header file XEventLog.h in appropriate project files (stdafx.h usually works well). There are two ways to construct CXEventLog object. Typical way is to construct object at runtime - for example, in app's InitInstance:

    CString str;
    str.LoadString(AFX_IDS_APP_TITLE);
    m_pEventLog = new CXEventLog(str);
If object is allocated from heap like above, don't forget to delete it!

The second way to construct CXEventLog object is to create local object:

    CXEventLog el;
    el.Init(_T("myapp"));
    el.Write(EVENTLOG_ERROR_TYPE, _T("This is a sample error."));
or you can also write this as:
    CXEventLog el(_T("myapp"));
    el.Write(EVENTLOG_ERROR_TYPE, _T("This is a sample error."));
You must call Init() if you do not specify app name in ctor.

With a CXEventLog object created, you can now call CXEventLog::Write() to log events. Note that the event log can be used for much more than just logging errors - see this FAQ for more information.

Frequently Asked Questions

  1. Does XEventMessage.dll have to be put in WINDOWS or other system directory?
    No! It is best not to put in system directory, and Microsoft discourages this too. Put XEventMessage.dll in same directory as your exe, or in some common directory (say, under Program Files\My Company\Common).

  2. I want to use XEventMessage.dll from several apps. Do I have to put it into each app's directory?
    No. The ctor second parameter is fully-qualified name of event message dll. This includes complete path and file name.

    Example:
    m_pEventLog = new CXEventLog("myapp", <BR>            "C:\\Program Files\\My Company\\Common\\XEventMessage.dll");
    The ctor second parameter is optional, and will default to the exe's directory if not specified.

  3. The demo app runs fine on Win98. Why do you say it won't work?
    The demo app may run without errors, but that's because there are stub APIs on Win9x that do nothing at all. There is no event log service on Win9x, so nothing gets logged! The good news is that your app will work on both NT and Win9x machines; the bad news is nothing is logged on Win9x.

  4. Can I use XEventLog in non-MFC apps?
    Yes. It has been implemented to compile with any Win32 program.

  5. Can I use XEventLog in a DLL?
    Yes.

  6. When I try to include XEventLog.cpp in my MFC project, I get the compiler error    "xeventlog.cpp(439) : fatal error C1010: unexpected end of file while looking for precompiled header directive".   How can I fix this?
    When using XEventLog in project that uses precompiled headers, you must change C/C++ Precompiled Headers settings to Not using precompiled headers for XEventLog.cpp.

            XEventLog demo screenshot

  7. The XEventMessage project in the download only has one configuration - Release. Don't I need XEventMessage Debug / Unicode configurations also, if my app has those configurations?
    No. The Release-mode XEventMessage.dll is the only one included because it's the only one that's needed, whether your app is compiled for Release, Debug, ANSI, or Unicode. Note that there is no code in DLL, so nothing needs to change.

  8. Do I have to recompile XEventMessage.dll before using it in my app?
    Not unless you want to test your compiler. It can be used "as is".

  9. Do I need to make registry changes before using XEventLog?
    No. XEventLog code creates the necessary registry keys for you, when you create CXEventLog object. To see what these registry keys are, please look at code.

  10. Does XEventLog delete the registry entries that it creates?
    No. In a production environment, it is assumed that app will be run more than once, so there is usually no requirement to delete the registry entries. Personally, I get really nervous when a program goes through my registry, deleting keys. The chances of messing up the whole system because of some simple programming mistake, is something I don't want to think about, especially when dealing with HKLM. I trust myself with Regedit more than I trust code someone has just handed me.

  11. Isn't it possible to include the compiled message resource in exe?
    Yes. It is possible, and this could be done if your situation requires it. For example, if you are only dealing with single exe, and there are reasons to distribute your app with as few files as possible, then this solution would make sense. My goal here is to present production-oriented solution - that is, environment where there are many apps, so that including message resource in each app just snowballs out of control.

    In production environments, my experience is that you must do whatever you can to modularize components, establish common (shared) code repositories, and do things only once instead of many times. In this way, you increase system robustness, and using same code over and over gives you confidence in common components. (This last is not appreciated until you have difficult system problem, and you must decide what to suspect, what to trust.)

  12. Why doesn't XEventLog support categories?
    If you look at any of the logs with NT Event Viewer, you will see that nearly all events have Category = None. I suspect this is because no one really knows what Category is for, or how it would help them. Having said that, the main reason for not supporting categories in XEventLog is that it would add extra complexity, with very little gain (IMHO).

  13. I included XEventLog in my app, but I get a lot of garbage in the Description box. What is wrong?
    You must copy XEventMessage.dll to exe directory. This means it must be in both Debug and Release directories. Note that even if XEventMessage.dll is missing, your message will still be logged, but it will have garbage in front of it in Description box. After you copy XEventMessage.dll to exe directory, refresh Event Viewer, and garbage will be gone.

  14. Can we use XEventLog and redistribute XEventMessage.dll in our (shareware/commercial) app?
    Yes, you can use XEventLog without charge or license fee. It would be nice to acknowledge my Copyright in your About box or splash screen, but this is up to you.

  15. Should I log only errors and other alerts to the event log, or can I use it for other kinds of messages?
    You can log any kind of information you want. For example, several commercial apps that I am familiar with use event log to log debug trace information. Since you lose all TRACE() output when you compile for Release, it is handy to be able to turn on some trace output for Release builds, especially if you have to go to customer's site. You can do this by creating registry (DWORD) flag, and then write to event log if flag is turned on (Use Regedit to create flag). The default, of course, is not to write. If you plan to do this, be sure event log size is set to appropriate value before you begin, and also be sure to disable flag when you are finished.

    Here is some pseudocode that will filter log output, based on flag:
        void DebugLog(LPCTSTR lpszString)
        {
            Get flag from registry.
            Is flag set?
            If so, call CXEventLog::Write()
        }
    Instead of calling CXEventLog::Write() directly for your debug trace output, you call DebugLog(), and it only writes to event log if flag is set. This centralizes debug output, so you don't have to search through code if you want to disable this feature, etc. A convenient place to put DebugLog() is in your CWinApp-derived class (another reason to declare CXEventLog object there).

    An interesting feature to add to DebugLog() is to use the Win32 function OutputDebugString() to optionally write to debugger. (Yes, this works fine in Release build). This is handy if used in conjunction with excellent DebugView from Sysinternals. So the above code could be written as:
        void DebugLog(LPCTSTR lpszString)
        {
            Get flag from registry.
            Is flag set?
            If so, call CXEventLog::Write().
            Get OutputDebugString flag from registry.
            Is flag set?
            If so, call OutputDebugString().
        }
    Using DebugView, the string will be displayed if OutputDebugString flag is set (Note: OutputDebugString flag is a DWORD key that you create in registry.)

    By using combination of writing debug trace to event log, and optionally to debugger, it will be much easier to diagnose Release-build problems.

  16. Why did you write CXEventLog?
    I got tired of looking at garbage in Description box, and even more tired of explaining to people why garbage was there. It looked like I didn't know what I was doing.

  17. Don't I need to include the message DLL's header file in my project? What is the connection between the CXEventLog class and the XEventMessage.dll?
    No, there is no need to include Message.h. There is only one piece of information that is needed by CXEventLog (besides the filename of XEventMessage.dll), and that is the fourth parameter to ReportEvent() - the event identifier. This is defined in the XEventMessage project file Message.h as
    #define GENERIC_MESSAGE  0x20000001L
    If you look at XEventLog.cpp, you will see that the fourth parameter to ReportEvent() is actually 0x20000001L. This eliminates the need to include Message.h, since there is no possibility that GENERIC_MESSAGE will change (there is only one message defined in the .mc file).

  18. So what is in XEventMessage.dll's .mc file?
    OK, here it is:
    MessageId=
    SymbolicName=GENERIC_MESSAGE
    Language=English
    %1
    .

Revision History

Version 1.0 - 4.16.03

  • Initial public release

Usage

This software is released into the public domain. You are free to use it in any way you like. If you modify it or extend it, please to consider posting new code here for everyone to share. This software is provided "as is" with no expressed or implied warranty. I accept no liability for any damage or loss of business that this software may cause.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Hans Dietrich
Software Developer (Senior) Hans Dietrich Software
United States United States
Member
I attended St. Michael's College of the University of Toronto, with the intention of becoming a priest. A friend in the University's Computer Science Department got me interested in programming, and I have been hooked ever since.
 
Recently, I have moved to Los Angeles where I am doing consulting and development work.
 
For consulting and custom software development, please see www.hdsoft.org.






Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralThanks a tonmemberafraz samina8 Oct '12 - 5:07 
Thanks you very much it help me to resolve me my issue very fast... Thanks once again
GeneralMy vote of 5memberHeatfanJohn18 Feb '12 - 7:51 
Great article and application. This code made it very easy to add event logging to my Windows Service application.
QuestionUsing in Windows 7/Vistamembermasteryoda2121 Jul '11 - 6:34 
You code writes a registry value in HKLM which has elevated security in Windows Vista/7 requiring the program to be run as administrator.
 
Do you see any way around this restriction?
QuestionSecurity logsmembergeogauci29 Mar '11 - 6:12 
Any idea how to implement the above to log in the security section (given you've got local system permissions) ?
AnswerRe: Security logsmentorHans Dietrich19 Apr '11 - 10:53 
I haven't found a way to do this yet.
Best wishes,
Hans
 

[Hans Dietrich Software]

QuestionWhat is the purpose of CXEventMessageApp?memberAdam J Richardson22 Mar '11 - 8:36 
Hi Hans,
 
I'm trying to fully understand the sample code. What is the purpose of the class in the message DLL? From reading the article and poking around on my own Windows systems, it seems like the class is completely unnecessary. Shouldn't the DLL just contain a mc-compiled message table?
 
Thanks.
AnswerRe: What is the purpose of CXEventMessageApp?mentorHans Dietrich22 Mar '11 - 9:22 
Adam J Richardson wrote:
Shouldn't the DLL just contain a mc-compiled message table?
The point of this article is to show an alternative to using the message compiler. The mc is the Microsoft-recommended technique. It is also IMHO tedious and requires you to maintain duplicate message strings (in some cases).
 
My suggestion is to try to set up a project using the mc, and then use my DLL. There is a good article on mc here: Using MC.exe, message resources and the NT event log in your own projects[^]
Best wishes,
Hans
 

[Hans Dietrich Software]

GeneralRe: What is the purpose of CXEventMessageApp?memberAdam J Richardson23 Mar '11 - 1:53 
Hi Hans,
 
My purpose is to truly understand what's going on in this Windows subsystem because it interests me. I am not trying to find a quick fix. With that in mind I have some questions.
 
I think I get the MSG00001.bin file. It is the output of mc-compiling Message.mc, yes? Seems we need mc just this once for our minimal message table and then we never need touch it again.
 
I still don't understand why there is a class declaration, definition and instantiation in the message DLL. The class (CXEventMessageApp) appears to do nothing. What is it for?
 
Thanks for reading.
GeneralDidn't see anything in XP Application Logmemberneumanndn8 Nov '10 - 18:35 
I extracted your example and ran the exe but ssaw nothing added to the Application log. Am I missing something? I'm using XP. I'm loggeds in as an admin.
 
Thanks, Doug Neumann
Question64 bitmemberyarongot6 Dec '09 - 2:58 
I have tried to compile the DLL in 64 bit and it says:
------ Build started: Project: XEventMessage, Configuration: Release x64 ------
Linking...
.\XEventMessage.def(4) : warning LNK4017: DESCRIPTION statement not supported for the target platform; ignored
&nbsp;&nbsp;   Creating library c:\projects\solutions\x64\release\XEventMessage.lib and object c:\projects\solutions\x64\release\XEventMessage.exp
CVTRES : fatal error CVT1100: duplicate resource.&nbsp;&nbsp; type:MESSAGETABLE, name:1, language:0x0409
LINK : fatal error LNK1123: failure during conversion to COFF: file invalid or corrupt
 
Any ideas?
AnswerRe: 64 bitmentorHans Dietrich19 Apr '11 - 11:00 
Were you able to compile it?
Best wishes,
Hans
 

[Hans Dietrich Software]

Questionhow to insert an own eventtype?membereinmahlc3 Dec '08 - 3:54 
Thanks for the ingeniously forged code concerning event logging.
Nevertheless I would like to get to know some special information:
 
The eventlog-viewer supports six event-types ( error, warning, information, success, success-audit, failure-audit), which come along with six icons.
For my project I attempted to insert an extra event-type into eventlog-viewer connected to an extra built icon, which, both, should work like system-supported event-types, described in your code, but I failed.
I was not able to insert a new eventtype to the just existing ones of the enum-list of the event-viewer. And I did not know where and how to insert an appropriate icon and how to connect both.
 
Have you an idea how to proceed in this operation?
 
Thanks chr
Answerlogging to System and custom logs: FIXED! [modified]memberMember 82353419 Nov '08 - 4:55 
reading the comments, some pepole seemed to have problem writing to System log etc. I had the same problems, trying to write to a custom log (I mean, why would you stuff your logs together with the already nicely filled System or Application ones?).
 
here's the deal: if you register a source "ID1" under Application, registering it again under System won't work: if you watch the registry, the multi-string Application.Sources has ID1 in it. This key is maintained by event log system, afaik it's the key that the logger uses to find out where to log ID1, and afaik ReportEvent will still log to Application->ID1.
 
to get your app to log to System->ID1, or MyLog->ID1, delete Application->ID1, and remove ID1 from Application->Sources. Then add the key System->ID1 key, then reboot, then log.
 
another problem I found out about: suppose you want to log to MyLog->ID1, and that doesn't exist yet, the first run of your program might still log to Application, simply because at the time you write ReportEvent, the registry/even log system isn't updated yet. Second run works though.
 
btw it took me some time to figure this out, mainly because when you fiddle too hard with the event logger, it gets stuck in a bad state: after some trying out, no matter what I did, all logs went to System->ID1, although I modified the Sources key, deleted registry entries etc. After a reboot all was fixed.
 

suggestions to the author:
- add an option to remove the created registry keys (there are just too many coders using the registry that never clean up. No wonder people complain their machine runs slowly after they installed/removed x programs)
- allow user to choose logging to Application or custom log
- add option to delete all created stuff (all reg keys, *.evt file created under %SYSTEMROOT%\System32 in case of custom log)
- maybe check if key is created or exists already, add a sleep() if it's created, else check values instead of overwriting them each time the progrm starts
- (this is personal preference): use tabs or spaces, preferrably spaces, but not both, your source will be much more readable; also spaces at the end of a line have no use at all
 
modified on Friday, November 21, 2008 5:43 AM

QuestionAny chance there will be an update to fully support the current version of Windows? Vista?memberMichael Avanessian10 Oct '08 - 4:36 
The description for Event ID 1 from source xxxxxxxxxx:xxxxxx.xxxx cannot be found. Either the component that raises this event is not installed on your local computer or the installation is corrupted. You can install or repair the component on the local computer.
AnswerRe: Any chance there will be an update to fully support the current version of Windows? Vista?mvpHans Dietrich10 Oct '08 - 22:55 
I copied the exe and dll in the demo download to Vista and tried it (running the exe "as administrator"). It worked exactly the same way it does on XP. Exactly the same entries in the event log.
 
Do you have the dll in the same directory as your exe?
 

GeneralREG_SZ or REG_EXPAND_SZmemberFranc Milan12 Jun '07 - 21:16 
On W2K3 server its not working properly because "::RegSetValueEx(.. _T("EventMessageFile").. REG_SZ ....) in method CXEventLog::RegisterSource. In Microsoft article (http://msdn2.microsoft.com/en-us/library/aa363634.aspx) its setting to "REG_EXPAND_SZ".
(sorry for my bad english).
GeneralGreat Code Simplifier!!!memberCT Buckweed13 Dec '05 - 9:11 
Windows can be so complicated at times. I just want to write strings to the event log. No messing with message compliers and what ever. This is just what the doctor ordered!
 
Thanks
GeneralEvent logging as a non-adminmemberchian2u2 Mar '05 - 12:22 
Hi,
First of all, thanks for the article, and code. It's great! However, I have one question. Does this code only work when the user is logged in as an administrator? I have this application that uses this code and it logs events fine when i am logged in as an admin. However, when I am logged in as a user, my application does not seem to log events. How can i get this working for non-admins. thanks. Any ideas are much appreciated.
 
Martin
GeneralXEventMessage DLLmemberKeithHurst17 Dec '04 - 1:33 

Hi,
 
many thanks for submitting this code which we can all use and learn from.
 
I do not code in VB or in C++ but use a compiler called Visual Objects for our Win32 development. It has full access to structures, pointers, dlls and the API.
 
I was hoping to use the XEventMessage.dll in our app so we could append to the log without having to create umteen message DLL files.
 
The code I use to add to the event log is :-
 
hEventLog := RegisterEventSourceA( String2PSZ( '' ), String2PSZ( 'CashfacVBT' ) )
IF hEventLog != Null_Ptr
cbStringSize := SLen( cString ) + 1
hMsgs := GlobalAlloc( 0x40, cbStringSize )
IF hMsgs != Null_Ptr
cString := cString + _Chr( 0 )
MemCopy( hMsgs, @cString, cbStringSize )
iNumStrings := 1
IF !ReportEventA( hEventLog, iLogType, 0, iEventID, Null_Ptr, iNumStrings, cbStringSize, hMsgs, hMsgs )
Information( NTrim( GetLastError() ) )
ENDIF
GlobalFree( hMsgs )
ENDIF
DeregisterEventSource( hEventLog )
ENDIF
 

I have registered the DLL in...
 
HKLM\System\CurrentControlSet\Services\EventLog\Application\TESTVBT
EventMessageFile REG_SZ C:\WinNT\System32\XEventMessage.dll
TypesSupported REG_DWORD 7
 
The XEventMessage dll does reside in the System32 folder.
 
WHen I view the log my messages are there, however they are still prefixed with the standard garbage.
 
Any ideas as to what it is I might be doing wrong ?
 
Many thanks
Keith Hurst
GeneralRe: XEventMessage DLLmemberKeithHurst17 Dec '04 - 5:15 

 
Guys,
 
I managed to get it up and running by reading a little more of what was going on here. All I had to do is make sure I had the GENERIC_MESSAGE define set up within my IDE and then used this to pass into ReportEvent.
 
Again, many thanks for this.
 
Regards
Keith Hurst
Generalthank's for the Article and the Demomemberavnersimon14 Nov '04 - 3:50 
Thank's a lot to you and others like Daniel Lohmann who spend time and
help us going over bstacles and to progress with our ability to wtite
inelegent and robust software.

GeneralRe: thank's for the Article and the DemomemberMember 463642227 Oct '08 - 16:49 
yes, this is such a great help!
I was looking for ages for a way to simplify the process of non-managed windows events. This is perfect.
Good explanation too Smile | :)
Thanks heaps.
GeneralAmazingmembersheck19 Aug '04 - 6:22 
A project that compiles without any errors and COMMENTS. Wow, I love these kinds of samples.
GeneralMultiple XEventMessage objectssussPaulS5 May '04 - 11:11 
I have not yet tried this but can you have multiple instances of the same XEventMessage objects running at the same time. I need to use logging in various places so instead of passing the same XEventMessage object around (possibly propagating the pointer to my XEventMessage object to other objects several layers deep), I just want to create an instance of the object where I need it. Would this cause any problems with registering the same application name multiple times?
 

GeneralGood article, helped me a lot...memberJigar Mehta30 Apr '04 - 21:38 
Hye,
This is a very good article... I appreciate this kind of article as it is ready to reuse in other projects...

Thanks!!! Rose | [Rose]
 
Jigar Mehta
(jigarmehta@gatescorp.com)
 
Software Developer
Gates Information Systems
Generalsome extensions like delte my eventlogmemberBardioc7 Apr '04 - 11:23 
Your project is very good thx was exactly the think I need for my project.
 
But one Question is it possible that my Application can delete the EventLog it made or to modyfy a older one?
 
MFG
Bardioc
Generalcreating event in mfc shared dllmemberXins10 Mar '04 - 16:54 
hii,
 
i'm developing a mfc dll program and i must make an event in my dll. how can i create an event for my dll using mfc shared dll and the event can be used in program that use this dll.
 
please help me if u have any idea, thx a lot.
 
regards,
 
-xins
GeneralA suggestion for improvingmemberR.Dietrich6 Mar '04 - 9:47 
It is a good idea to use only one DLL for multiply clients to log messages.
I have used parts of your code and improved it as follows:
 
1. I made a COM object with a simple interface that has only 3 functions like this:
 
LogError(BSTR sMsg);
LogWarning(BSTR sMsg);
LogInfo(BSTR sMsg);
 
2. I link the resource with the "dummy message" together with this COM object.
 
3. I register the component as usually.
 
4. Any client can use this component for logging without any registration
just calling one of the above interface methods.
(During the first call one of the interface methods the COM object
is registrating the calling client for logging!)
 

The advantage is:
- no class has to be used with the client code (thin code)
- the COM object itself is registering the client for logging
- the client must not know where the DLL is on your system
 
It works fine!
 
Reinhard Dietrich

GeneralRe: A suggestion for improvingmemberBasava12317 Mar '04 - 3:52 
Fantastic. It is very nice to have.
 
VB programmers just get the job done by having App.LogEvent(), while it is not so simplest for us.
 
Is there any way one can get the source and/or the binaries of the nice COM wrapper dll? And any useful readme.txt on the same?
It would be great.
 
Thanks.
 

 
Raju
GeneralRe: A suggestion for improvingmemberR.Dietrich17 Mar '04 - 8:19 
I'll do a small project on this subject and submit it to CodeProject soon...Smile | :)

Generalsend msg to 'System' Log...memberExcite13 Jan '04 - 13:38 
Hi! Hans,
 
I got another question, do you know how to send msg to NT Event Viewer Log, but go to 'System' or 'Security' or a custom Log??? I was using 'RegisterEventSource' function and then 'ReportEvent' function, but the msg will always display on Application Log. I also tried 'OpenEventLog' function to open other Logs (ie. System) and pass that handle to 'ReportEvent', and the msg did show up on System Log. However, because the source name is not there, I cannot open that particular msg.
Do you know how to send msg to other Logs and also able to resolved using DLL. I did put the DLL in the System Log Registry, that part is correct.
 
Thanks a lot!
- Eva

GeneralRe: send msg to 'System' Log...susssteveshurber17 Feb '04 - 11:47 
Eva,
 
I have the exact same question and I have not yet found a solution. Please let me know if you found something.
 
Steve

GeneralRe: send msg to 'System' Log...sussrkhuang2 Sep '04 - 8:16 

hi steve,
 
i'm having the same problem as Eva. did you ever figure it out? i really need to write to the 'System' log as well. any help?
 

Eva wrote:
Hi! Hans,
 
I got another question, do you know how to send msg to NT Event Viewer Log, but go to 'System' or 'Security' or a custom Log??? I was using 'RegisterEventSource' function and then 'ReportEvent' function, but the msg will always display on Application Log. I also tried 'OpenEventLog' function to open other Logs (ie. System) and pass that handle to 'ReportEvent', and the msg did show up on System Log. However, because the source name is not there, I cannot open that particular msg.
Do you know how to send msg to other Logs and also able to resolved using DLL. I did put the DLL in the System Log Registry, that part is correct.
 
Thanks a lot!
- Eva
 

GeneralRe: send msg to 'System' Log...memberyrleu5 Feb '06 - 23:12 

I have made it!

Modifying CXEventLog::RegisterSource to add a registry key to "SYSTEM\\CurrentControlSet\\Services\\Eventlog\\System\\" instead of "SYSTEM\\CurrentControlSet\\Services\\Eventlog\\Application\\" is enough. However, in CXEventLogTestDlg::CXEventLogTestDlg, the string resource AFX_IDS_APP_TITLE cannot be "XEventLogTest". I have tested several strings including "XEventLogTess", "XEventLogTesu", and other strings. All are OK--events can be inserted to the System log. But if AFX_IDS_APP_TITLE is "XEventLogTest", events are inserted into the Application log.

Pretty weird!!!

QuestionRe: send msg to 'System' Log... [modified]memberSiby Varghese13 Apr '07 - 6:19 
Does not seems to work for System or Security logs.
 
I am using this for my application and changing the AFX_IDS_APP_TITLE still logs to the applicationOMG | :OMG: log.
 
Please let me know if you found a solution. Cool | :cool:

 
Siby V
 

-- modified at 12:18 Monday 16th April, 2007
 
Update chumpies :
http://msdn2.microsoft.com/en-us/library/aa363679.aspx
As of Windows XP SP2, this parameter cannot be a handle to the Security log. To write an event to the Security log, use the AuthzReportSecurityEvent function.
 

-- modified at 15:04 Wednesday 18th April, 2007
 
Alrite : I am updating this since I got a work around.
As per MSDN security logging may not be possible. ( I am on XP here)
For logging as System Source you do this :
m_hEventLog = ::RegisterEventSource(NULL,"System");
 
Well this gets all your logs to the system log. But the garbage still exits.. so a workaround is to insert this before the RegisterEventSource
RegisterSource("System", lpszEventMessageDll);
This puts System under Application Registry and while viewing through event logger won't show garbage.

GeneralRe: send msg to 'System' Log...memberdtgbrown8 Feb '08 - 10:35 
In response to this statement:
"All are OK--events can be inserted to the System log. But if AFX_IDS_APP_TITLE is "XEventLogTest", events are inserted into the Application log.
 
Pretty weird!!!"
 
Did you delete the registry key 'XEventLogTest' found under application before running your test?
GeneralQuestion on SidmemberExcite12 Jan '04 - 14:11 
Hi!
 
I am writing a program to send NT Event msg to the NT Event Viewer Log and encountering the following problem... I want to use a existing userid on the box to send the msg to NT Event Viewer Log. I used 'LookUpAccountName' function to get th Sid from the userid and I was able to put the msg up to the Event Viewer Log(via 'ReportEvent'). However, the userid will display as the native NT id (S-1-39061...).
So, do you know how to have the actual userid display on the NT Event Viewer Log??? I mean the userid is valid (because if not, then it won't go thru 'LookUpAccountName' and cannot pass into 'ReportEvent' to send to the Viewer Log)
 
Thanks in advance!
- Eva

GeneralRe: Question on SidmemberHans Dietrich12 Jan '04 - 14:34 
In the CXEventLog::Write() method you will see the following code:
    // get our user name information
    PSID pSid = GetUserSid();
 
    LPCTSTR* lpStrings = &lpszMessage;
 
    bRet = ::ReportEvent(m_hEventLog,   // event log source handle
                         wType,         // event type to log
                         0,             // event category
                         0x20000001L,   // event identifier (GENERIC_MESSAGE)
                         pSid,          // user security identifier (optional)
                         1,             // number of strings to merge with message
                         0,             // size of binary data, in bytes
                         lpStrings,     // array of strings to merge with message
                         NULL);         // address of binary data

    if (pSid)
        HeapFree(GetProcessHeap(), 0, pSid);
This displays the user id in the event log record. Note that GetUserSid() is a private method in XEventLog.cpp.

GeneralRe: Question on SidmemberExcite12 Jan '04 - 14:55 
Hi! Hans,
 
Thanks for replying. Yes, I did read the 'GetUserSid' function that you wrote. What I'm looking for is if I want to say using a particular 'userid' which exist on the box(ie. tester1). Not using the userid which start the current process.
For example, the current process is start by 'Administrator'. But I want to use userid=tester1 to send this msg to Event Viewer Log. I was able to send the msg, but the USERID part on the NT Event Viewer Log listed as (S-1-3906...) instead of 'tester1'. Do you know how to make it to list as 'tester1' on the NT Event Viewer Log???
-- I did tried use 'GetCurrentProcess' and 'GetTokenInformation' and it will display the current process's userid correctly.
 
Thanks, Eva

GeneralRe: Question on SidmemberHans Dietrich12 Jan '04 - 18:18 
OK, I understand. I replaced call to GetUserSid() with this:
    // get our user name information
    //PSID pSid = GetUserSid();

    PSID pSid = NULL;
    DWORD cbSid = 0;
    char * pszDomain = NULL;
    DWORD cbDomain = 0;
    SID_NAME_USE snuType;
    BOOL bSuccess = FALSE;
 
    bSuccess = LookupAccountName((LPSTR) NULL, "user1",
            pSid, &cbSid, pszDomain, &cbDomain, &snuType);
 
    _ASSERTE(!bSuccess);  // API should have failed with insufficient buffer

    // now we have correct sizes for allocation

    pSid = (PSID) HeapAlloc(GetProcessHeap(), 0, cbSid);
 
    pszDomain = (char *) HeapAlloc(GetProcessHeap(), 0, cbDomain);
 
    bSuccess = LookupAccountName((LPSTR) NULL, "user1",
            pSid, &cbSid, pszDomain, &cbDomain, &snuType);
 
    _ASSERTE(bSuccess);
 
    LPCTSTR* lpStrings = &lpszMessage;
 
    bRet = ::ReportEvent(m_hEventLog,   // event log source handle
                         wType,         // event type to log
                         0,             // event category
                         0x20000001L,   // event identifier (GENERIC_MESSAGE)
                         pSid,          // user security identifier (optional)
                         1,             // number of strings to merge with message
                         0,             // size of binary data, in bytes
                         lpStrings,     // array of strings to merge with message
                         NULL);         // address of binary data

    if (pSid)
        HeapFree(GetProcessHeap(), 0, pSid);
    if (pszDomain)
        HeapFree(GetProcessHeap(), 0, pszDomain);
You will want to replace "user1" with your user id.
 


GeneralRe: Question on SidmemberExcite13 Jan '04 - 9:09 
Hi! Hans,
 
It works!!!! Thank you sooooooo much for your help! I rated 5 on this! =)
 
Thanks & Regards, Eva
P.S. I probably have other questions on Event Logging, but I will start a different email thread.

QuestionCan not removememberbugkiller7 Jan '04 - 5:27 
Hi,
 
First, thanks for your work. Now the problem is that we can not remove this file while uninstallation. What's the solution?
 
Thanks
 
kevin
AnswerRe: Can not removememberHans Dietrich7 Jan '04 - 7:45 
Have you tried deleting the registry entries first?

GeneralRe: Can not removememberbugkiller7 Jan '04 - 10:51 
yes. While I saw the registry was removed, then i delete the file manully, but still failed.
GeneralRe: Can not removememberHans Dietrich7 Jan '04 - 14:58 
Unless Event Viewer is running, there should not be a problem to delete the dll. I will let you know if I find anything more.
 


AnswerRe: Can not removememberchueh821 Nov '07 - 14:22 
I have the same issue too...
How to remove it when uninstall or re-install.
Thanks.
-Steel

GeneralXEventMessage.dll sourcememberchian2u10 Sep '03 - 13:59 
Hi Hans,
 
Great Example! Would you mind making the source code for XEventMessage.dll available? I don't really understand the message compiling part that well so I would like to compile it myself.
 
thanks,M
GeneralRe: XEventMessage.dll sourcememberHans Dietrich10 Sep '03 - 16:07 
Complete source is included in the download. The dll project is in the XEventMessage directory.
 
Best wishes,
Hans

GeneralOkay - I did it: A tutorial about how to get happy with mc.exememberDaniel Lohmann19 May '03 - 1:13 
Hi,
 
As Hans suggested, I wrote a tutorial about how to get happy with MC.exe and integrate it seamlessly into your VisualStudio build project:
 
Using MC.exe, message resources and the NT event log in your own projects

 
Note: The article is currently in the "unedited user items" area. The link will probably not work after it has been edited and moved to its final location.
 

BTW: The article also shows how to use FormatMessage() and ReportEvent(). And that categories do really work Poke tongue | ;-P
 
--
 
Daniel Lohmann
 
http://www.losoft.de
(Hey, this page is worth looking! You can find some free and handy NT tools there Big Grin | :-D )
QuestionWhy nobody seems to like MC?memberDaniel Lohmann16 May '03 - 12:04 
Good work, really Smile | :)
 
However, I find it a bit confusing that everybody seems to prefer string resources over the message compiler. Yes, it needs some time to learn how to deal with FormatMessage, MC-Files and how to integrate all this stuff seamless into the build environment. But today most of my projects do not contain string resources any more. I just use a MC-file for all strings of my apps. FormatMessage() offers great functionality!
 
I also never use separate message dlls (they are too messy Poke tongue | ;-P ) if dealing with the NT eventlog. I simply include the message resource in the .exe or (if shared) in a regular dll. Even if not that well known, you can also register an .exe as an event/category source for the eventlog.
 
Do you all find it really easier to deal with this clumsy string resource editor where you have to type \t for a tab and \n for a newline? Ever used it to enter the well formatted help (/?) message of a console app that offers 20 different options? Or to do a search/replace over all your strings?
 
--
 
Daniel Lohmann
 
http://www.losoft.de
(Hey, this page is worth looking! You can find some free and handy NT tools there Big Grin | :-D )

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130516.1 | Last Updated 23 Apr 2003
Article Copyright 2003 by Hans Dietrich
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid