哪种方法更适合在 C# 中读取 Windows 事件日志?WMI 或事件日志
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5411384/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Which approach is better to read Windows Event log in C#? WMI or EventLog
提问by istudy0
I need to write an application to grab event log for System/Applications. The other requirement is that I need to read event log every minute or so to grab the new event logs since I read last time. Currently I am considering to use C# to implement instead of C++.
我需要编写一个应用程序来获取系统/应用程序的事件日志。另一个要求是我需要每分钟左右读取一次事件日志以获取自上次读取以来的新事件日志。目前我正在考虑使用 C# 来实现而不是 C++。
With that I read several webpages and if I understand correctly, I can use either WMI or EventLog class to read event log. It seems to me that I can be notified when the new event log is added using EventLog class but I was not sure that is better than using WMI. If my understanding is correct, I would like to know which way I should take?
我阅读了几个网页,如果我理解正确,我可以使用 WMI 或 EventLog 类来读取事件日志。在我看来,当使用 EventLog 类添加新事件日志时,我可以收到通知,但我不确定这是否比使用 WMI 更好。如果我的理解是正确的,我想知道我应该走哪条路?
Please give me some advice. Thanks.
请给我一些建议。谢谢。
采纳答案by Alois Kraus
WMI is crap. It uses loads of memory and the "events" are achieved by polling internally. You can even set the poll interval. You are much better off to use the EventLog class of .NET. But if you need to read all logs from Windows Vista+ you must use the EventLogReaderwhere you can read events which define the events not via a message dll file located under
WMI是废话。它使用大量内存,“事件”是通过内部轮询实现的。您甚至可以设置轮询间隔。最好使用 .NET 的 EventLog 类。但是,如果您需要从 Windows Vista+ 读取所有日志,则必须使用EventLogReader,您可以在其中读取定义事件的事件,而不是通过位于下面的消息 dll 文件
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\eventlog\EventLogName\EventSourceName\EventMessageFile
but instead there is a ProviderGuid specified which is registered elsewhere. This makes it impossible to read many OS messages which use the new system. But you can use the EventLogReader class only on machines with an OS Version >= Vista. You will need two event log reader implementations depending on the installed OS if you need to get all messages. The EventLog class can also be made quite speedy when you read the messages in chunks of e.g. 100 messages from up to 4 threads which does improve reading speed up to a factor 2-3. I did get random errorsfor the Security Event Log on Windows Server 2003 when reading from it from multiple threads but for the others it worked very well from XP 32 Bit up to Windows 7 x64.
而是指定了一个在别处注册的 ProviderGuid。这使得无法读取许多使用新系统的操作系统消息。但是您只能在操作系统版本 >= Vista 的机器上使用 EventLogReader 类。如果您需要获取所有消息,您将需要两个事件日志阅读器实现,具体取决于安装的操作系统。当您从多达 4 个线程以 100 条消息的块读取消息时,EventLog 类也可以变得非常快,这确实将读取速度提高了 2-3 倍。从多个线程读取时,我确实收到了 Windows Server 2003 上的安全事件日志的随机错误,但对于其他线程,它从 XP 32 位到 Windows 7 x64 都运行良好。
回答by Ian
I know this is long after the original post, but I hope this is usefule to future searchers like myself who found the EventLog class too slow. Here is some code to demonstrate searching for the most recent System startup events:
我知道这是在原始帖子之后很久,但我希望这对像我这样发现 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"));
If you only want the most recent entry, this code took 0.28 seconds on my machine, compared with 7.11 seconds using EventLog class in place of the for() loop:
如果您只想要最新的条目,此代码在我的机器上花费了 0.28 秒,而使用 EventLog 类代替 for() 循环则为 7.11 秒:
var entry = (from EventLogEntry e in ev.Entries
where (e.InstanceId == 12)
&& e.TimeGenerated >= fromDate
orderby e.TimeGenerated
select e).LastOrDefault();
Hope it helps.
希望能帮助到你。
回答by AndyClaw
Check out the classes in the namespace System.Diagnostics.Eventing (and deeper) rather than using the EventLog class.
检查命名空间 System.Diagnostics.Eventing(和更深层次)中的类,而不是使用 EventLog 类。
When accessing a remote computer (maybe just Vista and later) using the EventLog class, the remote computer generates around 6 security audit entries as you connect to the logs, and another entry or 2 every time you retrieve a log record in a loop.
当使用 EventLog 类访问远程计算机(可能只是 Vista 和更高版本)时,远程计算机在您连接到日志时生成大约 6 个安全审核条目,并且在您每次在循环中检索日志记录时生成另一个或 2 个条目。
But with the EventLogQuery / EventLogReader / EventLogWatcher you can create an EventLogSession that keeps you connected. And you can retrieve specific entries using an XPath query whereas EventLog forces you to iterate over all entries to find an entry.
但是使用 EventLogQuery / EventLogReader / EventLogWatcher,您可以创建一个保持连接的 EventLogSession。您可以使用 XPath 查询检索特定条目,而 EventLog 强制您遍历所有条目以查找条目。
http://msdn.microsoft.com/en-us/library/bb671200.aspx
http://msdn.microsoft.com/en-us/library/bb671200.aspx
WARNING: To get the event message, the method EventLogRecord.FormatDescription() is hit-or-miss, and the property LevelDisplayName is also hit-or-miss. For this reason I am switching back to the EventLog class for retrieving the entries, and using the EventLogWatcher for watching entries.
警告:要获取事件消息,方法 EventLogRecord.FormatDescription() 是命中或未命中,并且属性 LevelDisplayName 也是命中或未命中。出于这个原因,我切换回 EventLog 类来检索条目,并使用 EventLogWatcher 来观察条目。