Reading and Querying EventViewer Efficiently With C#

This article is an extension is one my last posts on Event Viewer. Please the find the link below.

Working With EventViewer Using C# For Beginners

We'll be talking about the reading event logs. In my last article I explained about reading the event logs. But that is very slow because that loads all the event entries in memory and then iterates them one by one. Say if we have around one five thousand entries in the log then it will load all the entries in memory and then iterate them one by one. It makes the reading of logs very slow. Also at a certain point we might need to read the event logs on some specific criteria or want to read some specific logs then also we need to load all the events and iterate and find the required entry.

What if we want to read specific event logs with a specific type or with a specific specific level and so on. For that .NET 3.5 introduces new classes that are every helpful for querying the vent logs based on some criteria and they are very performance-oriented.

To start with, let's start with the basics so that you get a very good idea. An event entry in event viewer is also available in XML format and it is as:

<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
  <System>
    <Provider Name="MySource" />
    <EventID Qualifiers="0″>1004"</EventID>
    <Level>2</Level>
    <Task>0</Task>
    <Keywords>0×80000000000000</Keywords>
    <TimeCreated SystemTime="2013-08-15T16:21:21.000000000Z" />
    <EventRecordID>7</EventRecordID>
    <Channel>MyNewLog</Channel>
    <Computer>Brij-HP</Computer>
    <Security />
  </System>
  <EventData>
    <Data>An error has been generated by the application.</Data>
  </EventData>
</Event>

If we see the above then we can find it contains all the details of an event entry. Since all these data is available in XML tags we can write the queries based on it.

So let's first see the classes that we'll use to query the event logs.

  • EventLogQuery: It represents the query that will be used to fetch the events and other related information.
  • EventLogReader: Takes an EventLogQuery object as a parameter and allows us to read the events based on the query.
  • EventRecord: EventLogReader returns an EventRecord object that contains the basic details of the event entry.
  • EventLogRecord: This class implements EventRecord and provides additional details of the event like container and so on.

All the preceding classes were introduced with .NET 3.5 and provides super-fast reading of the class. Let's jump to the code.

string query = "*[System/EventID=903]";
EventLogQuery eventsQuery = new EventLogQuery("Application", PathType.LogName, query);
try
{
    EventLogReader logReader = new EventLogReader(eventsQuery);
    for (EventRecord eventdetail = logReader.ReadEvent(); eventdetail != null; eventdetail = 
    logReader.ReadEvent())
    {
        // Read Event details
    }
}
catch (EventLogNotFoundException e)
{
    Console.WriteLine("Error while reading the event logs");
    return;
}

The first string variable query contains the query for fetching the events. Here we have defind the query to fetch the event with EventID = 903. If we see the XML for the event that I used initially then we find that EventID comes under System so the query is defined as:

string query = "*[System/EventID=903]";

After that the instance of EventLogQuery was created that takes a parameter of .. and query. Then an EventLogReader instance was created that takes a parameter of type EventLogQuery. EventLogReader enables us to read the events. The ReadEvent() method reads the next event of the reader and if there is no next event then it returns null. We used the same logic in code above. The details of the event are in eventdetail.

So we can read the events based on the query provided. I'll here show you some sample queries and the details that can be used.

1. Reading all the event entries that is critical ( for critical level is 1)

string query = "*[System/Level=1]";

2. Reading all the event with EventRecordID as 7.

string query = "*[System/EventRecordID=7]";

3. Reading an element based on some element's attribute value. Reading all event entries that the provider name is "MySource".

string query = "*[System/Provider/@Name=\"MySource\"]";

Similarly, we can write a query for any element under System element as above. We can also write a query for some combinations using and/or as.

4. Reading all the event entries that are critical and error ( for critical level is 1 and for error it is 2).

string query = "*[System/Level=1 or System/Level=2]";

We can even provide the user the option to search based on search criteria and can create the query on the fly as well.


Similar Articles