Есть ли способ сказать, какой EventLog вызвал событие EntryWritten в C #? - PullRequest
5 голосов
/ 19 мая 2011

Я работаю над веб-приложением, которое отображает данные журналов событий, аналогично Event Viewer.Приложение также должно предоставлять пользователям возможность подписываться на журналы событий и получать уведомления, когда запись записывается в подписанные журналы, с использованием веб-службы.

Я использую этот код для подписки на журнал событий.в веб-сервисе:

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 вызываетсобытие?

Спасибо

Ответы [ 4 ]

4 голосов
/ 19 мая 2011

Я думаю, что проблема в том, что вся концепция класса EventLog состоит в том, что он предполагает, что он работает на одном журнале - что он и делает. Таким образом, ни класс EventWrittenEventArgs, ни класс EventEntry не содержат члена, содержащего имя журнала, как это неявно задается связанным экземпляром EventLog. Плохо, конечно, что вы не можете получить к нему доступ в обработчике EventWritten.

Вы можете создать оболочку вокруг 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 и может быть установлено для вашей «внешней» функции-обработчика.

3 голосов
/ 17 июня 2011

Другим вариантом будет использование отражения вдоль этих линий:

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

, поскольку sender в этом случае фактически имеет свойство Log.

2 голосов
/ 19 мая 2011

Я думаю, что то, что вы ищете, можно найти в 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 может дать вам достаточно информации для его поиска.

Надеюсь, это поможет некоторым.

0 голосов
/ 31 января 2017

Я согласен с идеей обёртывания класса 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);
        }

    }
...