Searching Event Log Entries






Searching Event Log Entries

Problem

Your application might have added many entries to 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, to which you'll add static methods allowing you to search for entries in an event log based on various criteria. 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 shown in Figure.

EventSearchLog class

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 Figure 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/csharpckbk2.)

Other possible search methods

Search method name

Entry property searched

FindCategory (overloaded to accept a string type category name)

Category == CategoryNameQuery

FindCategory (overloaded to accept a short type category number)

Category == CategoryNumberQuery

FindEntryType

EntryType == EntryTypeQuery

FindInstanceID

InstanceID == InstanceIDQuery

FindMachineName

MachineName == MachineNameQuery

FindMessage

Message == Message.Query

FindSource

Source == SourceQuery


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("InstanceId:     " + Entry.InstanceId);
	        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/3/2003, marked as Error type logs, and containing an event ID of 7000:

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

	    EventLogEntry[] Entries = EventLogSearch.FindTimeGeneratedAtOrAfter(Log.Entries,
	        DateTime.Parse("8/3/2003"));
	    Entries = EventLogSearch.FindEntryType(Entries, EventLogEntryType.Error);
	    Entries = EventLogSearch.FindInstanceId(Entries, 7000);

	    foreach (EventLogEntry Entry in Entries)
	    {
	        Console.WriteLine("Message:       " + Entry.Message);
	        Console.WriteLine("InstanceId:    " + Entry.InstanceId);
	        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 FindInstanceID method to search on the InstanceID. Initially, you would call the FindInstanceID 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 is returned by the EnTRies property of the EventLog class. The FindInstanceID method will return an array of EventLogEntry objects that match the search criteria (the value passed in to the second argument of the FindInstanceID 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 FindInstanceID method may be passed into another search method such as the FindEntryType method to narrow down the search to all entries that are a specific entry type (informational, error, etc.).

See Also

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



 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows