繁体   English   中英

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

[英]How to get a list of all Windows Event Logs (Event Viewer Logs) with their hierarchy and friendly names in C#

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

在此处输入图片说明

我遇到了一些问题。

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

此处的博客: EventSource NuGet 包和对 Windows 事件日志的支持(通道支持)有一个链接,指向一个罕见的EventSource 用户指南文档,该文档说明了这一点:

请使用 EventSourceAttribute 的 Name 属性为事件源表示的 ETW 事件提供程序提供描述性的限定名称。 默认值是事件源类型的短名称,这很容易导致冲突,因为 ETW 提供程序名称共享一个机器范围的命名空间。 一个好的提供者名称的例子“ <CompanyName>-<Product>-<Component> ”。 遵循此 3 元素约定将确保事件查看器在逻辑文件夹层次结构中显示您的事件日志: “Application and Services Logs/<CompanyName>/<Product>/<Component> ”。

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

对于不匹配的名称,有一个未记录的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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM