DekGenius.com
[ Team LiB ] Previous Section Next Section

Recipe 6.9 Searching Event Log Entries

Problem

Your application might have produced many entries in the event log. To perform an analysis of how the application operated, how many errors were encountered, and so on, you need to be able to perform a search through all of the entries in an event log. Unfortunately, there are no good built-in search mechanisms for event logs.

Solution

You will eventually have to sift through all the entries your application writes to an event log in order to find the entries that allow you to perhaps fix a bug or improve your application's security system. Unfortunately, there are no good search mechanisms for event logs. This recipe contains an EventLogSearch class, which contains many static methods allowing you to search for entries in an event log based on a criterion. In addition, this search mechanism allows complex searches involving multiple criteria to be performed on an event log at one time. The code for the EventSearchLog class is:

using System;
using System.Collections;
using System.Diagnostics;

public sealed class EventLogSearch
{
    private EventLogSearch( ) {}     // Prevent this class from being instantiated.

    public static EventLogEntry[] FindTimeGeneratedAtOrBefore(
        IEnumerable logEntries, DateTime timeGeneratedQuery)
    {
        ArrayList entries = new ArrayList( );

        foreach (EventLogEntry logEntry in logEntries)
        {
            if (logEntry.TimeGenerated <= timeGeneratedQuery)
            {
                entries.Add(logEntry);
            }
        }

        EventLogEntry[] entriesArray = new EventLogEntry[entries.Count];
        entries.CopyTo(entriesArray);
        return (entriesArray);
    }

    public static EventLogEntry[] FindTimeGeneratedAtOrAfter(
        IEnumerable logEntries, DateTime timeGeneratedQuery)
    {
        ArrayList entries = new ArrayList( );

        foreach (EventLogEntry logEntry in logEntries)
        {
            if (logEntry.TimeGenerated >= timeGeneratedQuery)
            {
                entries.Add(logEntry);
            }
        }

        EventLogEntry[] entriesArray = new EventLogEntry[entries.Count];
        entries.CopyTo(entriesArray);
        return (entriesArray);
    }
}

Discussion

Other searchable criteria can be added to this class by following the same coding pattern for each search method. For instance, the following example shows how to add a search method to find all entries that contain a particular username:

    public static EventLogEntry[] FindUserName(IEnumerable logEntries, 
        string userNameQuery)
    {
        ArrayList entries = new ArrayList( );

        foreach (EventLogEntry logEntry in logEntries)
        {
            if (logEntry.UserName == userNameQuery)
            {
                entries.Add(logEntry);
            }
        }

        EventLogEntry[] entriesArray = new EventLogEntry[entries.Count];
        entries.CopyTo(entriesArray);
        return (entriesArray);
    }

The methods shown in Table 6-2 list other search methods that could be included in this class and describe which property of the event log entries they search on. (All of these methods are implemented on the code for this book, which can be found at http://www.oreilly.com/catalog/csharpckbk.)

Table 6-2. Other possible search methods

Search method name

Entry property searched

FindMachineName
MachineName == MachineNameQuery
FindCategory (overloaded to accept a string type category name)
Category == CategoryNameQuery
FindCategory (overloaded to accept a short type category number)
Category == CategoryNumberQuery
FindSource
Source == SourceQuery
FindEntryType
EntryType == EntryTypeQuery
FindMessage
Message == Message.Query
FindEventID
EventID == EventIDQuery

The FindCategory method can be overloaded to search on either the category name or category number.

The following method makes use of the EventLogSearch methods to find and display entries that are marked as Error log entries:

public void FindAnEntryInEventLog( )
{
    EventLog Log = new EventLog("System");

    EventLogEntry[] entries = EventLogSearch.FindEntryType(Log.entries, 
                                                           EventLogEntryType.Error);

    foreach (EventLogEntry Entry in entries)
    {
        Console.WriteLine("Message:        " + Entry.Message);
        Console.WriteLine("EventID:        " + Entry.EventID);
        Console.WriteLine("Category:       " + Entry.Category);
        Console.WriteLine("EntryType:      " + Entry.EntryType.ToString( ));
        Console.WriteLine("Source:         " + Entry.Source);
    }
}

The following method finds and displays entries generated at or after 8/24/2002, are marked as Error type logs, and contain an event ID of 7000:

public void FindAnEntryInEventLog( )
{
    EventLog log = new EventLog("System");

    EventLogEntry[] entries = EventLogSearch.FindTimeGeneratedAtOrAfter(log.entries, 
                        DateTime.Parse("8/24/2002"));
    entries = EventLogSearch.FindEntryType(entries, EventLogEntryType.Error);
    entries = EventLogSearch.FindEventID(entries, 7000);

    foreach (EventLogEntry entry in entries)
    {
        Console.WriteLine("Message:        " + entry.Message);
        Console.WriteLine("EventID:        " + entry.EventID);
        Console.WriteLine("Category:       " + entry.Category);
        Console.WriteLine("EntryType:      " + entry.EntryType.ToString( ));
        Console.WriteLine("Source:         " + entry.Source);
    }
}

Note that this search mechanism can search within only one event log at a time.

To illustrate how searching works, let's assume that you are using the FindEventID method to search on the EventID. Initially, you would call the FindEventID search method, passing in a collection that implements the IEnumerable interface, such as the EventLogEntryCollection collection (that contains all entries in that event log) or an array of EventLogEntry objects. The EventLogEntryCollection collection is returned by the Entries property of the EventLog class. The FindEventID method will return an array of EventLogEntry objects that match the search criteria (the value passed in to the second argument of the FindEventID method).

The real power of this searching method design is that the initial search on the EventLogEntryCollection returns an array of EventLogEntry objects. This EventLogEntry array may then be passed back into another search method to be searched again, effectively narrowing down the search query. For example, the EventLogEntry array returned from the FindEventID method may be passed into another search method such as the FindEntryType method to narrow down the search to all entries that are possibly informational entry types.

See Also

See the "EventLog Class" and "EventLogEntry Class" topics in the MSDN documentation.

    [ Team LiB ] Previous Section Next Section