Sending messages into the event log seemed to me to be a fairly normal
thing to want to do, but apparently it is not since there seems to be many
people having problems with it... As I am.  I apologize in advance for this
being long, but there is a bit of code necessary to get the point across.

The short version of the problem:  I have application-specific EventIDs
that I want to use, but .NET does not like their size.

I want to write to the application log for the source MikeMessages, so I
first opened the log and wrote to it using the following lines:

<code>
using (EventLog evtlg = new EventLog("Application", ".", "MikeMessages")) {
  evtlg.Clear();
  try {
    evtlg.WriteEntry(null, EventLogEntryType.Error, 1, 0);
    Console.WriteLine("Wrote event!");
  } catch (Exception ex) {
    Console.WriteLine(ex.Message);
  }
} // using evtlg
</code>

The parameters on WriteEntry correspond to the message text, entry type,
eventid, and categoryid, respectively.

All is right in the world... my event was written, but there is no message
associated with EventID 1, so the log viewer says:

The description for Event ID ( 1 ) in Source ( MikeMessages ) cannot be
found. The local computer may not have the necessary registry information
or message DLL files to display .... blahblahblah

So, I made a resource DLL.  This was done by creating MikeMessages.mc with
the following contents:

<code>
MessageIdTypedef=DWORD

SeverityNames=(Success=0x0
               Informational=0x1
               Warning=0x2
               Error=0x3
              )

FacilityNames=(Interface=0x4)

MessageID=0x00000001
Facility=Interface
Severity=Error
SymbolicName=MSG_LAMENESS
Language=English
You are lame and should just kill yourself.
.
MessageID=0x00000002
Facility=Interface
Severity=Error
SymbolicName=MSG_BLAH
Language=English
Blah blah de blah de dee blah blah.
.
</code>

Then using the following commands at the command line, I got the
appropriate resource dll:

<commands>
mc -v -s -c MikeMessages.mc
rc -r -fo MikeMessages.res MikeMessages.rc
link -dll -noentry -out:MikeMessages.dll MikeMessages.res /MACHINE:x86
</commands>

You can then look at the MikeMessages.h header file and it will tell you
that the appropriate EventIDs for my events are some DWORD values:

<code>
#define MSG_LAMENESS   ((DWORD)0xE0040001L)
#define MSG_BLAH       ((DWORD)0xE0040002L)
</code>

Next, the registry needs to be told that I have this dll for the messages
and that it supports informational as well as error information.  So, at
HKLM\SYSTEM\CurrentControlSet\Services\Eventlog\Application\MikeMessages, I
set EventMessageFile to <my path>\MikeMessages.dll and TypesSupported to
dword:00000007.

All is right in the world and a command line event logger I got works
properly:

<commands>
logevent -s E -c 0 -r MikeMessages -e 3758358529 "Boom!"
</command>

The event logger smiles and the description for my event is "You are lame
and should just kill yourself.", which is what I expected.  It even has an
EventID of 1 in the log viewer, which is also nice.  If I try to log an
event with the C# code from above, it acts as before and tells me that I
don't have the DLL needed to register my events.

Now, finally, after all that, is the point:  WriteEvent takes an int, and
throws an error if I give it the proper value (which is the int-cast of
3758358529 aka -536608767), and doesn't log properly if I just lop off the
first half of my DWORD.  Here is the int-cast code:

<code>
int EventID;
unchecked {
  EventID = (int) 0xE0040001L;
}
</code>

Anybody got any ideas?  I'm tapped out.  Could there be any reason that MS
chose to throw this error instead of just passing it through?  A poke
through the IL shows that WriteEvent just call the native unsafe method
anyway (offset 01a5).

-Mike Hurwitz.
 Software Engineer
 FactSet Research Systems

You can read messages from the DOTNET archive, unsubscribe from DOTNET, or
subscribe to other DevelopMentor lists at http://discuss.develop.com.

Reply via email to