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.
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.
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.
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.