Paul said:
Here is the exact stament I use to log an event entry:
EventLog.WriteEntry("GIZMO",eventString,EventLogEntryType.Information,8001,7
)
I discovered through enumeration all of the event category strings
that are defined. The 7 produces the category "Network" which is
close to what my app does. I just dreamed up 8001, 8002, . I
tried all day yesterday with the help of MSDN to register two
additional categories: Exception and Trace Entry. I had no luck.
This shouldn't be so difficult. Everything else works great. The
Event Viewer displays GIZMO, the 8001 code, the category, and the
eventString data.Thanks for your prompt reply.
Adding event messages has been debased in .NET (its actually a copy of the
VB6 mechanism). It does not work the way that the event log was designed to
work, and IMO the reason why its been implemented so badly is sheer
laziness on the part of Microsoft.
The problem you have is because .NET does not use message/category resource
files (these are resource only DLLs). A resource file has a 'template', a
format string, for each message using place holders for insert strings, when
you add the event you provide the ID of the format string and the insert
strings. The FormatMessage API will extract the format string, and insert
the insert strings in the appropriate places to create the complete message.
When you install .NET you get a message resource file with 65,000 format
strings like this:
%1
ie there is no attempt to use the functionality of FormatMessage. Horrible
and lazy.
Category values are handled by the event log in a similar way. You have a
resource DLL that has entries for each category (but no insert string place
holders), the DLL is registered in the system registry as containing
category strings. When the event log sees that the message is from your
resource it will load the DLL, extract the resource, obtain the appropriate
category string and print it out. There is no default way to do this in .NET
(again, I think the reason is because the designers of this class haven't
really used the event log to do anything useful). So what you are seeing is
the default categories defined by the system.
You can add your own category file and remedy some of these problems.
Basically find the key for your event log source here:
HKLM\System\CurrentControlSet\Services\EventLog\Application
and then add the CategoryMessageFile value to point to the category file and
CategoryCount to indicate how many categories you have defined, here's some
code to do this:
// name is the source name
// msgFile is the full path to the category message file
// count is the number of categories
static void CreateSource(string name, string msgFile, int count)
{
if (!EventLog.SourceExists(name))
EventLog.CreateEventSource(name, "Application");
RegistryKey hklm = Registry.LocalMachine;
string keyName = @"SYSTEM\CurrentControlSet\Services"
+ @"\EventLog\Application\"
+ name;
RegistryPermission perm = new RegistryPermission(
RegistryPermissionAccess.Create|RegistryPermissionAccess.Write,
@"HKEY_LOCAL_MACHINE\"+keyName);
RegistryKey el = hklm.OpenSubKey(keyName, true);
string file = Environment.CurrentDirectory + @"\" + msgFile;
try
{
el.SetValue("CategoryMessageFile", file);
el.SetValue("CategoryCount", count);
}
catch(Exception){}
}
static void DeleteSource(string name)
{
if (!EventLog.SourceExists(SourceName)) return;
RegistryKey hklm = Registry.LocalMachine;
string keyName = @"SYSTEM\CurrentControlSet\Services"
+ @"\EventLog\Application\"
+ name;
RegistryPermission perm = new RegistryPermission(
RegistryPermissionAccess.Write,
@"HKEY_LOCAL_MACHINE\"+keyName);
RegistryKey el = hklm.OpenSubKey(keyName, true);
try
{
el.DeleteValue("CategoryMessageFile");
el.DeleteValue("CategoryCount");
}
catch(Exception){}
EventLog.DeleteEventSource(name);
}
Now you need to create a message resource file and then register it with the
method above.
This is part of the example CategoryFiles.zip on
http://www.grimes.demon.co.uk/Other_Stuff.htm
Richard