c# - 如何在 C# 中获取所有 Windows 事件日志(事件查看器日志)及其层次结构和友好名称的列表

标签 c# .net system.diagnostics etw event-viewer

我正在尝试从事件查看器中复制以下内容:

enter image description here

我在一些事情上遇到了麻烦。

  1. 我取回的一些名称不是显示名称或友好名称。例如,对于“Microsoft Office 警报”,我只返回“OAlerts”。我怎样才能从“OAlerts”获得完整的“Microsoft Office 警报”?
  2. 找出层次结构。看来我所能做的就是解析破折号并做出某种最佳猜测。 API 中似乎没有一种简单的方法来解决这个问题。 GetLogNames 只是为您提供所有日志的简单列表

    EventLogSession session = new EventLogSession();
    List<string> logNames = new List<string>(session.GetLogNames());
    foreach (string name in logNames)
    {
        //EventLogConfiguration config = new EventLogConfiguration(name); //looks useful but doesn't give me any of the info i'm looking for.
    
       Console.WriteLine(name);
    }  
    

最佳答案

此博客在这里:The EventSource NuGet package and support for the Windows Event Log (Channel Support)有一个罕见的 EventSource User's Guide 的链接说明这一点的文件:

Do use the EventSourceAttribute’s Name property to provide a descriptive, qualified name for the ETW event provider represented by your event source. The default is the short name of your event source type, which can easily lead to collisions, as ETW provider names share one machine-wide namespace. An example of a good provider name “<CompanyName>-<Product>-<Component>”. Following this 3-element convention will ensure Event Viewer displays your event logs in a logical folder hierarchy: “Application and Services Logs/<CompanyName>/<Product>/<Component>”.

这往往表明破折号更像是一种约定而不是严格的要求(所以我相信你可以自己解析它)。请注意,该博客仍开放征求意见。

至于不匹配的名称,有一个未记录的 EvtIntGetClassicLogDisplayName 函数可以让您在事件查看器中显示名称。以下是如何将它与 session 和日志名称一起使用:

    static void Main(string[] args)
    {
        var session = new EventLogSession();
        foreach (string name in session.GetLogNames())
        {
            Console.WriteLine(GetDisplayName(session, name));
        }
    }

这里是支持代码(因为它没有记录,使用风险自负,而且它似乎主要用于这个“OAlert”条目,所以我不确定它是否值得):

    public static string GetDisplayName(EventLogSession session, string logName)
    {
        var sb = new StringBuilder(512);
        int bufferUsed = 0;
        if (EvtIntGetClassicLogDisplayName(GetSessionHandle(session).DangerousGetHandle(), logName, 0, 0, sb.Capacity, sb, out bufferUsed))
            return sb.ToString();

        return logName;
    }

    private static SafeHandle GetSessionHandle(EventLogSession session)
    {
        return (SafeHandle)session.GetType().GetProperty("Handle", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(session);
    }

    [DllImport("wevtapi.dll", CharSet = CharSet.Unicode)]
    private static extern bool EvtIntGetClassicLogDisplayName(IntPtr session, [MarshalAs(UnmanagedType.LPWStr)] string logName, int locale, int flags, int bufferSize, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder displayName, out int bufferUsed);

关于c# - 如何在 C# 中获取所有 Windows 事件日志(事件查看器日志)及其层次结构和友好名称的列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37662342/

相关文章:

c# - 调用 net tcp 端点时,具有 net tcp 和 http 绑定(bind)的 WCF 服务不会激活

c# - 最新 Autofac 版本不支持 .Net Framework 4.6.2

c# - 使用 C# 检查进程是否正在远程系统上运行

c# - 如何识别流程是否需要输入?

c# - 在 ASP.NET MVC 4 中将缓存设置为最高级别

c# - 什么是 Plugin CRM 2011 中的 Context、serviceFactory 和 Service

c# - 将现有代码优先模型和流畅的 API 配置从 Entity Framework 6 移植到 Entity Framework Core 2.0

c# - 控制 System.Diagnostics.Process.Start C# 的 Action

javascript - 如何将转发器 onclick 按钮的项目中的数据传递给 javascript 文件以在 ajax 中使用

c# - 从窗口类名获取窗口句柄