c# – 高效,快速地读取Windows日志

我想要完成的是一个C#应用程序,它将从
Windows事件日志中读取日志并将它们存储在其他地方.这必须很快,因为安装它的一些设备会产生大量的日志/秒.

到目前为止,我尝试了三种方法:

本地WMI:它不能正常工作,由于需要加载的集合的大小导致错误和异常太多.
EventLogReader:我虽然这是一个完美的解决方案,因为它允许您通过使用XPath表达式查询事件日志.问题是,当您想要获取每个日志的消息内容时(通过调用FormatDescription()),需要花费太多时间来进行长集合.
例如:如果我回过头来,我可以在0.11秒内读取12k日志.
如果我为每个日志添加一行来存储消息,则需要将近6分钟才能完成相同的操作,这对于如此少的日志来说是完全疯狂的.
我不知道是否可以对EventLogReader进行任何类型的优化以便更快地获取消息,我在MS文档和Internet上都找不到任何东西.

我还发现您可以使用名为EventLog的类来读取日志条目.但是,此技术不允许您输入任何类型的过滤器,因此您基本上必须将整个日志列表加载到内存中,然后根据您的需要将其过滤掉.
这是一个例子:

EventLog eventLog = EventLog.GetEventLogs().FirstOrDefault(el => el.Log.Equals("Security", StringComparison.OrdinalIgnoreCase));
var newEntries = (from entry in eventLog.Entries.OfType()
orderby entry.TimeWritten ascending
where entry.TimeWritten > takefrom
select entry);

尽管在获取消息方面速度更快,但内存的使用可能很高,我不希望在部署此解决方案的设备上引起任何问题.

任何人都可以帮我吗?我找不到任何解决方法或方法来实现这样的事情.

谢谢!.

最佳答案 我们讨论了一些关于阅读注释中现有日志的内容,可以通过访问以下内容来访问安全标记的日志:

 var eventLog = new EventLog("Security");
 for (int i = 0; i < eventLog.Entries.Count; i++)
 {
      Console.WriteLine($"{eventLog.Entries[i].Message}");
 }

这可能不是最干净(以性能为导向)的方式,但我怀疑任何其他方法会更快,因为你自己已经通过尝试不同的技术找到了.
Alois发布的一个小编辑:EventLogReader并不比EventLog更快,特别是当使用上面代码块中显示的for循环机制时,我认为EventLog更快 – 它只访问循环内的条目对于它们的索引,Entries集合只是一个引用,而在使用EventLogReader时,它将首先执行查询并循环遍历该结果,这应该更慢.正如Alois的帖子所评论的那样:如果您不需要使用查询选项,只需使用EventLog变体即可.如果确实需要查询,请使用EventLogReader,因为它可以在比使用EventLog时更低的级别进行查询(只有LINQ查询,这比执行查找时查询要慢).

为了防止您将来再次遇到这种麻烦,并且因为您说您正在运行服务,我将使用EventLog类的EntryWritten事件:

    var eventLog = new EventLog("Security")
    {
        EnableRaisingEvents = true
    };
    eventLog.EntryWritten += EventLog_EntryWritten;

    // .. read existing logs or do other work ..

    private static void EventLog_EntryWritten(object sender, EntryWrittenEventArgs e)
    {
        Console.WriteLine($"received new entry: {e.Entry.Message}");
    }

请注意,必须将EnableRaisingEvents设置为true才能在记录新条目时触发事件.启动(例如)Task也是一个很好的做法(也是性能方面的),这样系统就不会在排队调用事件时锁定自己.

如果要检索所有新创建的事件,此方法可以正常工作,如果要检索新创建的事件但对这些事件使用查询(过滤器),则可以查看EventLogWatcher类,但在您的情况下,如果没有约束,我只是使用EntryWritten事件,因为你不需要过滤器和简单的旧简单.

点赞