Какой подход лучше читать журнал событий 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 для просмотра записей.