我需要编写一个应用程序来获取系统/应用程序的事件日志。另一个要求是我需要每分钟左右读取一次事件日志以获取自上次读取以来的新事件日志。目前我正在考虑使用C#来实现而不是C++。
有了它,我阅读了几个网页,如果我理解正确,我可以使用 WMI 或 EventLog 类来阅读事件日志。在我看来,当使用 EventLog 类添加新事件日志时可以通知我,但我不确定这是否比使用 WMI 更好。如果我的理解是正确的,我想知道我应该采取哪种方式?
请给我一些建议。谢谢。
我知道这是在原始帖子之后很久,但我希望这对像我这样发现 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 秒,而使用 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();
希望能帮助到你。
WMI是垃圾。它使用大量内存,“事件”是通过内部轮询来实现的。您甚至可以设置轮询间隔。最好使用 .NET 的 EventLog 类。但是,如果您需要从 Windows Vista+ 读取所有日志,则必须使用EventLogReader,您可以在其中读取定义事件的事件,而不是通过位于下的消息 dll 文件
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\eventlog\EventLogName\EventSourceName\EventMessageFile
而是指定了一个在其他地方注册的 ProviderGuid。这使得无法读取许多使用新系统的操作系统消息。但是您只能在 OS 版本 >= Vista 的机器上使用 EventLogReader 类。如果您需要获取所有消息,您将需要两个事件日志阅读器实现,具体取决于已安装的操作系统。当您从多达 4 个线程中读取 100 条消息的块中的消息时,EventLog 类也可以变得非常快速,这确实将读取速度提高了 2-3 倍。从多个线程读取 Windows Server 2003 上的安全事件日志时,我确实遇到了随机错误,但对于其他线程,它从 XP 32 位到 Windows 7 x64 运行良好。
检查命名空间 System.Diagnostics.Eventing(以及更深层次)中的类,而不是使用 EventLog 类。
当使用 EventLog 类访问远程计算机(可能只是 Vista 和更高版本)时,远程计算机会在您连接到日志时生成大约 6 个安全审核条目,并且每次您在循环中检索日志记录时都会生成另一个或 2 个条目。
但是使用 EventLogQuery / EventLogReader / EventLogWatcher,您可以创建一个让您保持联系的 EventLogSession。您可以使用 XPath 查询检索特定条目,而 EventLog 会强制您遍历所有条目以查找条目。
http://msdn.microsoft.com/en-us/library/bb671200.aspx
警告:要获取事件消息,EventLogRecord.FormatDescription() 方法是命中或未命中,属性 LevelDisplayName 也是命中或未命中。出于这个原因,我切换回 EventLog 类来检索条目,并使用 EventLogWatcher 来观察条目。