Custom Windows Event Log Strangeness (or, why does Exists exist?)

If you’re writing a Windows service, or even a windows application, the idea of writing to a windows event log is appealing.  After all, there’s a decent tool for reading it, it’s easy to read and write from, and it handles things like rollover so you don’t have to roll your own solution.  So, you might have a piece of code that looks something like this:

public static void LogError(string error, EventLogEntryType level)
{           
        if (!EventLog.SourceExists(Name))
        {
            EventLog.CreateEventSource(Name, Name);
        }
        System.Diagnostics.EventLog log = new EventLog(Name);
        log.Source = Name;
        log.MaximumKilobytes = MaxKilobytes;
        log.WriteEntry(error, level);
}

This has the advantage of letting you define your own event log name and register a source for it, so you can create something in the Application Logs section of the event viewer.  The documentation on MSDN is pretty straightforward on this, and says that CreateEventSource throws an ArgumentException if the name is already in use, hence the call to SourceExists. 

The strange part of the equation is the event log name.  I noticed when I tried running a test and Creating “Custom Event Source 1” and “Custom Event Source 2”, that I got an ArgumentException when I tried creating the sources.  The names are different, so you’d think they should work, but the exception details said that the first 8 characters matched an existing log name.  Yes, even in Windows 7, 8.3 will never die…  Here’s what’s strange, even adding EventLog.Exists(Name) doesn’t work, because the method will still return false even if creating the source will throw an exception.  Since there’s no method in the EventLog class that checks for a similar log name (instead of just an identical one), I created my own.  This code checks for a similar log name, and if one is found uses it, but it’s simple enough to modify to do whatever you want. 

private static void CreateSource(string name)
{
    try
    {
        if (!EventLog.SourceExists(Name))
        {
            //look for a similar log name   
            if (LogExistsSimilar(ref name) == false)
                EventLog.CreateEventSource(Name, Name);
            else
            {
                string oldName = Name;
                Name = name;  //use the similar log name
            }
        }
    }
    catch (ArgumentException ex)
    {
        Name = "Application";
    }
}

//need to compare the first 8 characters of a log name
private static bool LogExistsSimilar(ref string name)
{
    foreach (EventLog e in EventLog.GetEventLogs())
    {
        if (e.LogDisplayName.StartsWith(name.Substring(0, 8)))
        {
            name = e.LogDisplayName;
            return true;
        }
    }
    return false;
}

This is just something to keep in mind if you want to create custom event logs (which I think is a good idea), and want to be able to customize what they’re called at runtime (or at least configuration time).  In my case, I need to be able to install multiple instances of a UCMA service on one server, and I want to be able to separate the logging for each of them.  Now this means I can call the logs whatever I want, as long as the first 8 characters of the log name are unique.

Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s