【问题标题】:How to get a list of all Windows Event Logs (Event Viewer Logs) with their hierarchy and friendly names in C#如何在 C# 中获取所有 Windows 事件日志(事件查看器日志)及其层次结构和友好名称的列表
【发布时间】:2016-10-06 08:25:52
【问题描述】:

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

我遇到了一些问题。

  1. 我得到的一些名称不是显示名称或友好名称。例如,对于“Microsoft Office Alerts”,我只返回“OAlers”。如何从“OAlers”获取完整的“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);
    }  
    

【问题讨论】:

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


    【解决方案1】:

    此博客在此处:The EventSource NuGet package and support for the Windows Event Log (Channel Support) 有一个指向罕见的 EventSource User's Guide 文档的链接,该文档声明如下:

    请务必使用 EventSourceAttribute 的 Name 属性来提供 ETW 事件提供程序的描述性限定名称,由 你的事件源。默认是您的事件源的短名称 类型,这很容易导致冲突,因为 ETW 提供程序名称共享 一个机器范围的命名空间。一个好的提供者名称的例子 “&lt;CompanyName&gt;-&lt;Product&gt;-&lt;Component&gt;”。按照这个 3 元素 约定将确保事件查看器以 逻辑文件夹层次结构:“Application and Services Logs/<CompanyName>/<Product>/<Component>”。

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

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

        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);
    

    【讨论】:

    • 谢谢西蒙。多么棒的答案。 GetDisplayName 就像一个魅力(虽然使用 DangerousGetHandle 很可怕——我想知道这是否会通过代码审查:)。然而,命名约定似乎并没有正确地坚持。即使在上面我添加的屏幕截图中,Microsoft-SQLServerDataTools 也没有放在 Microsoft 之下。此外,当我调用 GetLogNames() 时,我看到 Microsoft-IIS-Configuration 在上面的屏幕截图中没有显示在 Microsoft 下。我认为可能还有另一个像您发现的那样“隐藏”的 API。
    • 类似的例子是 Microsoft-Rdms-UI 日志。
    • Microsoft-SQLServerDataTools 根本不遵循 3 元素约定(只有 2 个部分,MS 的一些人没有阅读文档......)。此外,如果您检查 EventViewer 的菜单 View/Show Analytic and Debug Logs,会显示很多东西。这些日志标有“诊断”或“分析”。至于 Microsoft-IIS-Configuration,它是一个链接到提供程序“Microsoft-Windows-IIS-Configuration”的日志(您可以使用new ProviderMetadata("Microsoft-Windows-IIS-Configuration", session, null).LogLinks 发现该链接)。日志和它们的提供者之间的命名空间并不总是一致的......
    猜你喜欢
    • 2015-10-14
    • 1970-01-01
    • 1970-01-01
    • 2023-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-01
    • 1970-01-01
    相关资源
    最近更新 更多