【问题标题】:Which approach is better to read Windows Event log in C#? WMI or EventLog在 C# 中读取 Windows 事件日志哪种方法更好? WMI 或事件日志
【发布时间】:2011-03-23 20:43:45
【问题描述】:

我需要编写一个应用程序来获取系统/应用程序的事件日志。另一个要求是我需要每分钟左右读取一次事件日志以获取自上次读取以来的新事件日志。 目前我正在考虑用C#代替C++来实现。

我阅读了几个网页,如果我理解正确,我可以使用 WMI 或 EventLog 类来阅读事件日志。 在我看来,当使用 EventLog 类添加新事件日志时可以通知我,但我不确定这是否比使用 WMI 更好。 如果我的理解是正确的,我想知道我应该走哪条路?

请给我一些建议。谢谢。

【问题讨论】:

    标签: c# windows wmi logging event-log


    【解决方案1】:

    我知道这是在原始帖子之后很久,但我希望这对像我这样发现 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();
    

    希望对你有帮助。

    【讨论】:

    • 这个方法很快。谢谢。
    • @Ian,我通过将 EventLog 默认构造函数更改为 EventLog("security","re​​moteMachineName","re​​moteIP") 为远程计算机执行了您的代码。在调试器中,我看到远程机器一天写了近 250000 个条目。并且遍历所有这些已经花费了10分钟的时间,请建议是否有更好的方法来遍历远程emachine事件日志。
    • @Ian,我见过 EventLogEntry Listeners..但是这对于远程计算机 EventLog 的可行性和正确性有多大。请您分享您的想法。谢谢!
    【解决方案2】:

    WMI 是垃圾。它使用大量内存,“事件”是通过内部轮询来实现的。您甚至可以设置轮询间隔。最好使用 .NET 的 EventLog 类。但是,如果您需要从 Windows Vista+ 读取所有日志,则必须使用EventLogReader,您可以在其中读取定义事件的事件,而不是通过位于下的消息 dll 文件

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

    而是指定了一个在别处注册的 ProviderGuid。这使得无法读取许多使用新系统的操作系统消息。但是您只能在 OS 版本 >= Vista 的机器上使用 EventLogReader 类。如果您需要获取所有消息,您将需要两个事件日志阅读器实现,具体取决于已安装的操作系统。 当您以块的形式阅读消息时,EventLog 类也可以变得非常快。来自多达 4 个线程的 100 条消息,这确实将阅读速度提高了 2-3 倍。从多个线程读取 Windows Server 2003 上的安全事件日志时,我确实得到了random errors,但对于其他线程,它从 XP 32 位到 Windows 7 x64 运行良好。

    【讨论】:

      【解决方案3】:

      检查命名空间 System.Diagnostics.Eventing(以及更深层次)中的类,而不是使用 EventLog 类。

      当使用 EventLog 类访问远程计算机(可能只是 Vista 和更高版本)时,远程计算机会在您连接到日志时生成大约 6 个安全审核条目,并且每次您在循环。

      但是使用 EventLogQuery / EventLogReader / EventLogWatcher,您可以创建一个 EventLogSession 让您保持联系。您可以使用 XPath 查询检索特定条目,而 EventLog 会强制您遍历所有条目以查找条目。

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

      警告:要获取事件消息,EventLogRecord.FormatDescription() 方法是命中或未命中,属性 LevelDisplayName 也是命中或未命中。出于这个原因,我切换回 EventLog 类来检索条目,并使用 EventLogWatcher 来观察条目。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-03-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-08
        • 1970-01-01
        • 2012-11-22
        • 1970-01-01
        相关资源
        最近更新 更多