Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / Win32

Real Time Event Log Reader

4.37/5 (12 votes)
7 May 2018CPOL3 min read 35.8K   1.3K  
RealTimeEventLogReader will show you how to read event logs in C# as soon as they are written in Windows Event Logs.

Introduction

RealTime Event Log Reader is useful to read Windows event logs in realtime, i.e., Read log as soon as they are written in Windows Event Logs.

Consider a case where some other application(s) are writing event logs very fast. In this case, if we use EventLog.EntryWritten Event to read the latest logs, then this event will be raised as soon as the entry is added to Windows event logs. Which then slows down or hang the application.

The solution to this problem is here. I am using EventLogQuery and EventLogReader class to read most recent events.

LogReader class calculates the elapsed time since previous event read. Then using the filter on creation time, it reads the log written in between the elapsed time.

These records are then posted to main window to display it on grid.

On running RealTimeEventLogReader, it will not show any logs until something is written to Windows event logs.

RealTimeEventLogReader will not read existing logs which were there in windows event logs before running the RealTimeEventLogReader.

  • Enter the Log Name on below window and click Ok.

    Log Name

  • After clicking on OK button, If it is a valid Log Name, the below window will be shown.

    Main Window

  • Generate some logs by starting/ stopping some services.
  • Double click on any entry in the grid.

    Details

Using the Code

Download source code here - 

https://www.codeproject.com/KB/tips/1242641/RealTimeEventLogReader.zip

EventLogRecord.cs

C#
public EventLogRecord(EventRecord eventdetail)
{
            eventID = eventdetail.Id;
            detailsXML = eventdetail.ToXml();
            taskCategory = eventdetail.Task.Value;
            timestamp = eventdetail.TimeCreated.Value;
            source = eventdetail.ProviderName;
            //level = (LogLevel)eventdetail.Level.Value;
            levelString = eventdetail.LevelDisplayName;
            logName = eventdetail.LogName;
            eventData = GetEventData(eventdetail);
}

Ctor takes the EventRecord object as a parameter and creates the EventLogRecord object.

EventLogRecord is used to display logs in Grid.

LogReader.cs

C#
public delegate void AddRecordDelegate(EventLogRecord record);

public AddRecordDelegate AddRecord;

AddRecordDelegate is used to post the EventRecord object to the main window.

C#
private Thread readerThread = null;
private DateTime _lastReadTime = DateTime.UtcNow;
private const string TimeFormatString = "yyyy-MM-ddTHH:mm:ss.fffffff00K";
private const string EventReaderQuery = "*[System/TimeCreated/@SystemTime >='{0}']";
  • readerThread is a thread which is used to read the event logs on a timely basis.
  • _lastReadTime is used to calculate the elapsed time.
  • TimeFormatString to format local time into the event record format.
  • EventReaderQuery is the query to read events based on creation time.

Thread Main Loop

C#
private void ReadLogs()
        {
            while (!Stop)
            {
                // 1. Calculate elapsed time since previous read.
                double elapsedTimeSincePreviousRead = (DateTime.UtcNow - _lastReadTime).TotalSeconds;
                DateTime timeSpanToReadEvents = 
                    DateTime.UtcNow.AddSeconds(-elapsedTimeSincePreviousRead);
                string strTimeSpanToReadEvents = 
                    timeSpanToReadEvents.ToString(TimeFormatString, CultureInfo.InvariantCulture);
                string query = string.Format(EventReaderQuery, strTimeSpanToReadEvents);
                int readEventCount = 0;

                // 2. Create event log query using elapsed time.
                // 3. Read the record using EventLogReader.
                EventLogQuery eventsQuery = new EventLogQuery(LogName, PathType.LogName, query) 
                                            { ReverseDirection = true };
                EventLogReader logReader = new EventLogReader(eventsQuery);

                // 4. Set lastReadTime to Date.Now
                _lastReadTime = DateTime.UtcNow;

                for (EventRecord eventdetail = logReader.ReadEvent(); 
                           eventdetail != null; eventdetail = logReader.ReadEvent())
                {
                    byte[] bytes = null;
                    if (eventdetail.Properties.Count >= 2)
                    {
                        bytes = (byte[])eventdetail.Properties[eventdetail.Properties.Count-1].Value;
                    }
                    EventLogRecord record = new EventLogRecord(eventdetail);

                    // 5. Post record read using event log query.
                    // if (parser.IsValid(temporaryRecord))
                    {
                        PostDetail(record);
                    }
                    // 6. Post only latest InternalLogLimit records, 
                    // if result of event log query is more than InternalLogLimit.
                    if (++readEventCount >= LogLimit)
                    {
                        break;
                    }
                }
                Thread.Sleep(ReadInterval);
            }          
        }

ReadLogs is the thread startup method. Which is used to read event logs using the EventLogQuery and EventLogReader.

  • The above method first calculates the elapsed time since previous read and creates the query string to read events.
  • Using the query string EventLogQuery object is created.
  • Using EventLogQuery object, events are read using EventLogReader.
  • Using the for loop post the records using PostDetail method.

PostDetail() Method

C#
private void PostDetail(params EventLogRecord[] records)
        {
            if (AddRecord != null && records != null)
            {
                //Return each record in the list to the viewer using AddRecord
                foreach (EventLogRecord record in records)
                {
                    if (record != null)
                    {
                        AddRecord.BeginInvoke((EventLogRecord)record.Clone(), null, null);
                    }
                }
            }
        }

The above method invokes the AddRecord delegate. This method is handled in MainWindow.cs.

MainWindow.cs

AddRecord() Method

C#
private void AddRecord(EventLogRecord record)
        {
            eventLogRecordList.Add(record);
            toolStripStatusLabelNumCount.Text = eventLogRecordList.Count.ToString();
            toolStripStatusLabelStatusString.Text = "Started";
            if (eventLogRecordList.Count >= reader.LogLimit)
            {
                eventLogRecordList.RemoveAt(0);
            }
            gvLogs.FirstDisplayedScrollingRowIndex = gvLogs.RowCount - 1;

        }

eventLogRecordList is used to maintain list of EventLogRecord. Also used to bound to grid to display the records in grid.

Real time Event Log Reader displays recent 5000 records in grid. Once the limit is reached, it starts deleting the items from the bottom of the list. This prevents Real time Event Log Reader from memory leak.

Points of Interest

Using the EventLog.EntryWritten Event to read the events in real time can hang the application if the event generation is too fast.

We need to use list appropriately, if we forget to clean-up older records from list then after some long time, it leads to memory leak.

 

History

08 May 2018 - Added a link to download source code.

 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)