Какой подход лучше читать журнал событий Windows на С#? WMI или EventLog

Мне нужно написать приложение для захвата журнала событий для System/Applications. Другим требованием является то, что мне нужно каждую минуту читать журнал событий, чтобы захватить новые журналы событий, так как я читал последний раз. В настоящее время я планирую использовать С# для реализации вместо С++.

С этим я прочитал несколько веб-страниц, и если я правильно понял, я могу использовать либо WMI, либо класс EventLog для чтения журнала событий. Мне кажется, что я могу получать уведомления, когда новый журнал событий добавляется с использованием класса EventLog, но я не был уверен, что это лучше, чем использование WMI. Если мое понимание правильное, я хотел бы знать, каким образом я должен взять?

Пожалуйста, дайте мне несколько советов. Спасибо.

Ответ 1

WMI - это дерьмо. Он использует массу памяти, а "события" достигаются путем опроса внутри страны. Вы даже можете установить интервал опроса. Вам гораздо лучше использовать класс EventLog.NET. Но если вам нужно прочитать все журналы из Windows Vista +, вы должны использовать EventLogReader, где вы можете читать события, которые определяют события не через сообщение dll, расположенный в

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

но вместо этого указан ProviderGuid, который зарегистрирован в другом месте. Это делает невозможным чтение многих сообщений ОС, которые используют новую систему. Но вы можете использовать класс EventLogReader только на машинах с версией ОС → Vista. В зависимости от установленной ОС вам понадобятся две программы чтения журнала событий, если вам нужно получить все сообщения. Класс EventLog также может быть довольно быстрым, когда вы читаете сообщения в кусках, например. 100 сообщений до 4 потоков, что улучшает скорость чтения до 2-3 раз. Я получил случайные ошибки для журнала событий безопасности в Windows Server 2003 при чтении из него из нескольких потоков, но для других он отлично работал с XP 32 бит до Windows 7 x64.

Ответ 2

Я знаю, что это уже давно после первоначального сообщения, но я надеюсь, что это будет полезно для будущих поисковиков, таких как я, которые слишком быстро обнаружили класс EventLog. Ниже приведен код, демонстрирующий поиск самых последних событий запуска системы:

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"));

Если вы хотите только самую последнюю запись, этот код занял 0,28 секунды на моей машине, по сравнению с 7.11 секундами, используя класс EventLog вместо цикла for():

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

Надеюсь, что это поможет.

Ответ 3

Ознакомьтесь с классами в пространстве имен System.Diagnostics.Eventing(и глубже), а не с использованием класса EventLog.

При доступе к удаленному компьютеру (возможно, только к Vista и более поздней версии) с использованием класса EventLog на удаленном компьютере генерируется около 6 записей аудита безопасности при подключении к журналам и еще одна запись или 2 каждый раз, когда вы извлекаете запись журнала в цикл.

Но с EventLogQuery/EventLogReader/EventLogWatcher вы можете создать EventLogSession, который будет поддерживать вас. И вы можете получить определенные записи с помощью запроса XPath, тогда как EventLog заставляет вас перебирать все записи, чтобы найти запись.

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

ПРЕДУПРЕЖДЕНИЕ. Чтобы получить сообщение о событии, метод EventLogRecord.FormatDescription() является хитом или пропуском, а свойство LevelDisplayName также является хитом или пропуском. По этой причине я возвращаюсь к классу EventLog для извлечения записей и используя EventLogWatcher для просмотра записей.