Which approach is better to read Windows Event log in C#? WMI or EventLog

19,610

Solution 1

WMI is crap. It uses loads of memory and the "events" are achieved by polling internally. You can even set the poll interval. You are much better off to use the EventLog class of .NET. But if you need to read all logs from Windows Vista+ you must use the EventLogReader where you can read events which define the events not via a message dll file located under

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\eventlog\EventLogName\EventSourceName\EventMessageFile

but instead there is a ProviderGuid specified which is registered elsewhere. This makes it impossible to read many OS messages which use the new system. But you can use the EventLogReader class only on machines with an OS Version >= Vista. You will need two event log reader implementations depending on the installed OS if you need to get all messages. The EventLog class can also be made quite speedy when you read the messages in chunks of e.g. 100 messages from up to 4 threads which does improve reading speed up to a factor 2-3. I did get random errors for the Security Event Log on Windows Server 2003 when reading from it from multiple threads but for the others it worked very well from XP 32 Bit up to Windows 7 x64.

Solution 2

I know this is long after the original post, but I hope this is usefule to future searchers like myself who found the EventLog class too slow. Here is some code to demonstrate searching for the most recent System startup events:

EventLog ev = new EventLog()
{
    Log = "System"
};
SystemSession sess;

DateTime t1 = DateTime.Now;
DateTime t2 = DateTime.Now;
DateTime fromDate = DateTime.Now.AddDays(-30);
TimeSpan t;
int i, j=0;

t1 = DateTime.Now;
for (i = ev.Entries.Count - 1; i >= 0; i--)
{
    if (ev.Entries[i].TimeGenerated < fromDate) break;

    if (ev.Entries[i].InstanceId == 12)
    {
        //do something ...
        break;
    }
}
t2 = DateTime.Now;

t = new TimeSpan(t2.Ticks - t1.Ticks);
string duration = String.Format("After {0} iterations, elapsed time = {2}",
    ev.Entries.Count - i,
    t.ToString("c"));

If you only want the most recent entry, this code took 0.28 seconds on my machine, compared with 7.11 seconds using EventLog class in place of the for() loop:

var entry = (from EventLogEntry e in ev.Entries
         where (e.InstanceId == 12)
         && e.TimeGenerated >= fromDate
         orderby e.TimeGenerated
         select e).LastOrDefault();

Hope it helps.

Solution 3

Check out the classes in the namespace System.Diagnostics.Eventing (and deeper) rather than using the EventLog class.

When accessing a remote computer (maybe just Vista and later) using the EventLog class, the remote computer generates around 6 security audit entries as you connect to the logs, and another entry or 2 every time you retrieve a log record in a loop.

But with the EventLogQuery / EventLogReader / EventLogWatcher you can create an EventLogSession that keeps you connected. And you can retrieve specific entries using an XPath query whereas EventLog forces you to iterate over all entries to find an entry.

http://msdn.microsoft.com/en-us/library/bb671200.aspx

WARNING: To get the event message, the method EventLogRecord.FormatDescription() is hit-or-miss, and the property LevelDisplayName is also hit-or-miss. For this reason I am switching back to the EventLog class for retrieving the entries, and using the EventLogWatcher for watching entries.

Share:
19,610

Related videos on Youtube

istudy0
Author by

istudy0

Updated on January 11, 2020

Comments

  • istudy0
    istudy0 over 4 years

    I need to write an application to grab event log for System/Applications. The other requirement is that I need to read event log every minute or so to grab the new event logs since I read last time. Currently I am considering to use C# to implement instead of C++.

    With that I read several webpages and if I understand correctly, I can use either WMI or EventLog class to read event log. It seems to me that I can be notified when the new event log is added using EventLog class but I was not sure that is better than using WMI. If my understanding is correct, I would like to know which way I should take?

    Please give me some advice. Thanks.

  • Alexandru Dicu
    Alexandru Dicu about 11 years
    This method is fast. Thank you.
  • SaiKiran Mandhala
    SaiKiran Mandhala over 9 years
    @Ian, I executed your code for a remote computer by changing the EventLog default constructor to EventLog("security","remoteMachineName","remoteIP"). In the debugger i have seen that the remote machine has written almost 250000 entries for a single day. And looping through all of them has taken 10 minutes of time, Please suggest if there is any better way to loop through remote emachine event logs.
  • SaiKiran Mandhala
    SaiKiran Mandhala over 9 years
    @Ian, I have seen EventLogEntry Listeners..but how far this feasible and correct for a remote computer EventLog. Request you to please share your ideas. Thanks!

Related