有没有办法告诉哪个EventLog在C#中导致了EntryWritten事件?

时间:2011-05-18 22:43:45

标签: c# .net event-log

我正在开发一个显示事件日志数据的Web应用程序,类似于事件查看器。该应用程序还必须为用户提供一种方式,以便在使用Web服务将条目写入订阅日志时订阅事件日志并接收通知。

我正在使用此代码订阅Web服务中的事件日志:

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

我正在尝试使用观察者作为事件日志的订阅者,并且在处理EventWritten事件时,调用一个观察者的Update方法。问题是,我不知道如何区分事件日志,因为它们都使用相同的事件处理程序。我这样做是因为事件日志的数量因机器而异。此外,我希望观察者只处理一种类型的EventLog,即。当一个事件写入应用程序日志时,一个观察者会发送一封电子邮件。

我使用这行代码获取当前计算机上的所有日志:

remoteEventLogs = EventLog.GetEventLogs(machineName);

EventWritten事件处理程序具有此对象发送者参数,但Visual Studio将其类型显示为EventLogInternal,我无法使用,并且我无法将发送者强制转换为EventLog以获取EventLog.Log属性。如果我尝试投射它,就像这样:

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

我得到一个例外,说我不能将EventLogInternal转换为EventLog。

有没有办法知道哪个EventLog会触发事件?

由于

5 个答案:

答案 0 :(得分:4)

我认为问题在于,EventLog类的整个概念是它假设它在单个Log上运行 - 它就是这样做的。因此,EventWrittenEventArgsEventEntry类都不包含包含Log-name的成员,因为它是由关联的EventLog-instance隐式赋予的。当然,糟糕的是,你无法在EventWritten-handler中找到它。

您可以围绕System.Diagnostics.EventLog创建一个包装器,如下所示:

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

然后在通常使用MyEventLog的地方使用EventLog。可能会给它一个更好的名字。

您还可以通过提供从Action<string, EntryWrittenEventArgs>内部调用的MyEventLog_EntryWritten属性来分解“您的代码”部分,并且可以将其设置为“外部”处理函数。

答案 1 :(得分:3)

另一种选择是沿着这些方向使用反射:

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

因为在这种情况下sender实际上具有Log属性。

答案 2 :(得分:2)

我认为您正在寻找的内容可以在EntryWrittenEventArgs中找到。

MSDN显示有一个名为Entry的属性,它向您显示有关刚刚记录的内容的各种信息。在EventLogEntry类中有一些可能对您有帮助的属性,例如MachineName或UserName。

这是Args类的链接 http://msdn.microsoft.com/en-us/library/system.diagnostics.entrywritteneventargs.aspx

这是Entry类的链接 http://msdn.microsoft.com/en-us/library/system.diagnostics.eventlogentry.aspx

我没有看到指向特定事件日志的直接链接,但如果您使用调试器在该类中查找,则Entry对象可能会为您提供足够的信息来查找它。

我希望这会有所帮助。

答案 3 :(得分:0)

我同意按照Christian的建议将EventLog类包装在另一个类中的想法。我最近研究过这样的要求。

这是我创建的课程

 public class EventLogWatcher : EventLog
{
    Action<string, EntryWrittenEventArgs> _changeHandler;
    public EventLogWatcher(string logName, Action<string, EntryWrittenEventArgs> changeHandler)
        : base(logName)
    {
        _changeHandler = changeHandler;
    }

    public void EnableCapture()
    {
        base.EnableRaisingEvents = true;
        base.EntryWritten += EventLogChangeHandler;
    }

    public void DisableCapture()
    {
        base.EnableRaisingEvents = false;
        base.EntryWritten -= EventLogChangeHandler;
    }

    private void EventLogChangeHandler(object sender, EntryWrittenEventArgs e)
    {
        _changeHandler(base.Log, e);
    }
}

这是用法

 foreach (string eventlogType in LogTypes)
            logWatchers.Add(new EventLogWatcher(eventlogType, EventLogChangeHandler));

        foreach (EventLogWatcher localLog in logWatchers)
        {
            try
            {
                localLog.EnableCapture();
            }
            catch(Exception ex)
            {
                EventManager.PublishExceptionLogMessage(ex);
            }
        }
        EventManager.PublishInfoLogMessage($"Started EventLog listeners for {string.Join(",", LogTypes)} logs");

 private void EventLogChangeHandler(string eventLogType, EntryWrittenEventArgs e)
    {
        try
        {
            if (UploadAllowed(eventLogType, e))
            {

                Dm.EventLog model = _eventLogEntryMapper.MapEntryToModel(e);
                Task.Factory.StartNew(
                       () => _eventLogUploadService.UploadEventLog(model),
                       _cancellationTokenProvider.Token,
                       TaskCreationOptions.None,
                       TaskScheduler.Default);
            }
        }
        catch(Exception ex)
        {
            EventManager.PublishExceptionLogMessage(ex);
        }

    }

答案 4 :(得分:0)

另一种选择是像这样更改事件注册:

eventLog.EntryWritten += (sender, e) => eventLog_EntryWritten(eventLog, e);