Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to tell which EventLog caused the EntryWritten event in C#?

Tags:

c#

.net

event-log

I'm working on a web application that shows event logs data, similar to Event Viewer. The application also has to provide a way for users to subscribe to event logs and receive notifications when an entry is written to subscribed logs, using a web service.

I'm using this code to subscribe to an event log in the web service:

EventLog eventLog = new EventLog(observer.logName, observer.machineName);
eventLog.EnableRaisingEvents = true;
eventLog.EntryWritten += new EntryWrittenEventHandler(eventLog_EntryWritten);
eventList.Add(eventLog);

I'm trying to use observers as subscribers to event logs, and when an EventWritten event is handled, call the Update method of one observer. The problem is, I don't know how to differentiate event logs, since they all use the same event handler. I'm doing this because the number of event logs differs from one machine to another. Also, I want observers to handle only one type of EventLog, ie. one observer would send an e-mail when an event is written to the Application log.

I use this line of code to get all logs on the current computer:

remoteEventLogs = EventLog.GetEventLogs(machineName);

EventWritten event handler has this object sender parameter, but Visual Studio shows its type as EventLogInternal, which I can't use, and I can't cast the sender to EventLog to get EventLog.Log property. If I try to cast it, like this:

void eventLog_EntryWritten(object sender, EntryWrittenEventArgs e)
    {
        var log = (EventLog)sender;
    }

I get an exception saying I can't cast an EventLogInternal to EventLog.

Is there a way to know which EventLog fires the event?

Thanks

like image 325
markhan777 Avatar asked May 18 '11 22:05

markhan777


2 Answers

I think the problem is, that the whole concept of the EventLog class is that it assumes it works upon a single Log - which it does. So neither the EventWrittenEventArgs nor the EventEntry class sport a member that contains the Log-name, as it is implicitly given by the associated EventLog-instance. Bad is of course, that you cannot get to it inside the EventWritten-handler.

You could create a wrapper around System.Diagnostics.EventLog, like so:

class MyEventLog : EventLog
{
    public MyEventLog(string logName, string machineName)
        : base(logName, machineName)
    {
        base.EnableRaisingEvents = true;
        base.EntryWritten += MyEventLog_EntryWritten;
    }

    void MyEventLog_EntryWritten(object sender, EntryWrittenEventArgs e)
    {
        Console.WriteLine("Entry in {0} log.", base.Log);

        // Your code
    }
}

Then use MyEventLogin places where you normally would use EventLog. Probably give it a better name though.

You could also factor out the "Your Code" part by providing an Action<string, EntryWrittenEventArgs> property that is being called from inside MyEventLog_EntryWritten and can be set to your "external" handler function.

like image 160
Christian.K Avatar answered Sep 30 '22 15:09

Christian.K


Another option would be to use reflection along these lines:

string log = (string)sender.GetType().GetProperty("Log").GetValue(sender, null);

since sender in this case actually has the Log property.

like image 44
Jakob Avatar answered Sep 30 '22 15:09

Jakob