65.9K
CodeProject 正在变化。 阅读更多。
Home

日志向导 - 查看 Windows 事件日志也可以很有趣!

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.64/5 (5投票s)

2016年1月21日

GPL3

14分钟阅读

viewsIcon

31048

downloadIcon

1065

您可以对 Windows 事件日志进行高级搜索。甚至支持正则表达式搜索和过滤。无需专业技能。

目录

Log Wizard 系列的其他文章

介绍, 过滤器, 注释

引言

查看 Windows 事件日志可能相当痛苦。至少可以说,默认的事件查看器界面很奇怪(比如,它浪费了很多空间)。对于现有的替代方案,我在这里要添加一个新的——Log Wizard

我创建了Log Wizard,以帮助任何人轻松地过滤日志以识别 bug 和/或问题。它支持几种类型的日志,并且从版本1.7开始,它还支持 Windows 事件日志。我在github上托管它,计划大约每 3-4 周发布一个新版本。

查看、过滤和/或搜索的过程必须非常简单。如果不是这样,我显然做错了什么——请告诉我!

入门:简明版

一旦启动 Log Wizard,它会等待您打开日志。只需按 Ctrl-O(等同于 Actions >> Open Log)。

选择 Windows Event Log,然后按 OK。事件将开始传入——随着它们的显示,您将在状态栏中看到进度。根据您的事件日志的大小,这可能需要几秒钟,但 UI 始终保持响应。

我将显示来自 ApplicationSystem 事件日志的事件,并将它们合并在一起。

请注意,最新的事件在前——因此,在等待旧事件的同时,您可以快速查看最近发生的事情。

作为预览,请尝试 Ctrl-F(查找),输入一些内容(甚至是正则表达式),然后享受预览。或者,尝试 Ctrl-G(跳转到行/时间)并输入类似 -10h(相对于您选定的行,跳转到 10 小时前)或 -2.5d(跳转到 2.5 天前)的内容。

或者,只需浏览事件,您就会发现我已经尽我所能利用了每一寸空间来显示相关信息。您可以切换信息以显示/隐藏,直到只看到对您来说重要的内容。

入门:详细版

Ctrl-O 并选择 Windows Event Log 后,您可以当然也可以根据自己的喜好调整一些设置。

首先需要注意的是,您可以同时查看多个(Windows 事件)日志。它们将按日期/时间排序。您可以打开 Local Logs(默认)或 Remote Logs(稍后详述)。

打开本地日志

Event Log(s) 文本框中,您可以输入任何 Windows 事件日志的名称——一旦被识别,就会显示绿色的“OK”(每行一个条目)。

或者,您可以选中/取消选中下方列表中的日志(这显然更容易 :))——文本框将更新以反映您的选择。

文本框下方列表的问题是,您不能保证列表是完整的。枚举所有 Windows 事件日志相当麻烦,几乎不可能。在 .NET 中,我们有 EventLog.GetEventLogs([remote_machine_name]),但这只会返回很少的日志名称。或者简单地说,就是常见的日志。它甚至不会显示 System 日志!

为了解决这个问题,我将访问 C:\Windows\System32\winevt\Logs——并显示最近更新的文件。不幸的是,这是一个非常长的列表,而且大多数日志都是空的。

要了解某个日志是否为空,唯一的方法就是打开它并开始读取。当然,这很耗时。您将看到,当涉及到读取 Windows 事件日志时,一切都是耗时的

为了帮助您判断哪些日志值得关注,我在事件日志下方的文本框旁边提供了一个 Test 按钮。它将打开一个新窗口,显示您选择的哪些日志包含条目——并且还会显示每个日志的条目数(即使对于远程计算机也有效,前提是您已正确设置密码)。

一旦您对选择满意,只需点击底部的 OK,Log Wizard 就会开始收集并显示日志中的信息。

打开远程日志

您也可以连接到远程日志。我已经使其过程尽可能无缝和轻松。要连接到远程计算机,您需要提供计算机名称、域、用户名和密码。

设置好后,您会看到一个 Test 按钮,显示您是否成功连接到远程计算机。连接成功后,(选中的)事件日志列表会更新。

您可以从列表中选中/取消选中日志,或手动输入远程计算机上 Windows 事件日志的名称。一旦名称正确,您就会看到绿色的“OK”。

选择完要查看的日志后,点击底部的 OK。Log Wizard 现在将收集并显示日志中的信息。

需要注意的是,Log Wizard 会记住您的选择,因此下次打开 Log Wizard 时,它会重新打开您上次选择的内容。如果您连接到远程计算机,它不会在本地存储密码——它会强制您重新输入。一旦密码正确,它将重新读取日志并显示给您。

随心所欲地调整

正如我已经说过的,我不喜欢浪费(UI)空间。任何您不喜欢的东西,都可以将其关闭。我的意思是:

视图窗格

根据您的日志类型,它可能包含很多列。在 View Pane 中,您希望在“摘要/详细信息”之间取得最佳平衡,这样就不会有太多列,但也不会太少。对于 Windows 事件日志,默认情况下,我显示消息、行号、日期、时间、级别(其余部分显示在详细信息窗格中)。

您决定什么对您很重要:首先,您可以调整列的宽度和/或移动它们。要移动列,请右键单击其标题。将出现一个菜单,您可以将该列移到其左侧或右侧(参见底部的操作)。

您还可以显示/隐藏任何列——只需右键单击任何列标题。这里,我只是显示了日志和类别

详细信息窗格

默认情况下,Details Pane 显示除行号、日期、时间、级别列之外的所有内容。它们显示在第一行(固定行),第二行是可移动的,其中显示完整的消息。您当然也可以调整详细信息窗格的大小和/或自定义它。

自定义详细信息窗格时,您可以显示/隐藏列,并指定它们显示在哪里(在哪个行)。右键单击它,然后选择“Edit Description Layout”。

您应该能够轻松地修改它以满足您的需求。例如:

随心所欲地切换!

任何您不想要的内容都可以切换掉。甚至 Details Pane!只需按 Alt-D 关闭,然后按 Alt-D 重新打开。或者状态栏 - Alt-S 打开/关闭。

您甚至可以切换标题栏(Alt-T

要查看可以打开/关闭的内容(并立即看到它的含义),您可以按 Actions >> Show/Hide Information(您需要显示状态栏才能使“Actions”按钮可见)。

在 Windows 事件日志中搜索文本

这是 Log Wizard 真正出色的地方之一。无论您在日志的哪个位置,只需键入 Ctrl-F(查找)。

您可以搜索任何内容,并获得即时预览(周围 1000 行)

如您所见,搜索正则表达式非常方便。有几点需要注意:

  • 默认情况下,Log Wizard 会搜索所有列。您可以关闭它,在这种情况下,它只会搜索 Message 列。
  • Log Wizard 会尝试猜测您的文本是否为正则表达式。您可以覆盖它。
  • 您的搜索将被保存,以便下次执行 Ctrl-F 时可以重新选择它。

按下 OK 后,它将带您到第一个结果。

您会发现找到的文本会以粗体和不同的背景显示,以便您可以轻松地在视觉上看到结果。

如果您的搜索将您带到视图中不可见(仅在详细信息窗格中可见)的结果,Log Wizard 将在不同的背景中显示整行(这里,搜索 .net runtime)。

在上例中,第 55534 行在 Source 列中包含 .net runtime 文本。

您可以轻松地在结果之间导航——只需按 F3(查找下一个)或 Shift-F3(查找上一个)。

F3 / Shift-F3 相对于您当前选定的行。您可以转到任何行,然后按 F3 或 Shift-F3——搜索将从那里继续。或者……

您可以轻松地切换仅查看搜索结果。只需按 Ctrl-Alt-F,您就会看到如下内容:

再次按下它,您将返回查看完整的日志。

要停止搜索(并停止对找到的单词进行着色),只需按 ESCAPE 键。

过滤

在检查 Windows 事件日志时,与任何日志一样,会有很多您不关心的信息。因此,您可以简单地将其过滤掉。Log Wizard 提供 3 种类型的过滤器:

  • 排除过滤器(您将从视图中排除行)
  • 包含过滤器(您将从视图中包含行——所有 Include 过滤器都将进行 OR 操作)
  • 颜色过滤器(您可以为特定行应用漂亮的颜色)

需要注意的是,您的查找(Ctrl-F)将在您现有的视图上工作。也就是说,Find 命令将忽略您通过过滤排除的每一行。

我在这里深入解释了过滤器。要轻松地为某些单词着色,只需选择它们,右键单击,选择 Set Color of Lines >> Match Color,选择颜色,然后就完成了。在这种情况下,resolution 显示为蓝色,ping 显示为红色。

当您过滤掉一些内容后,如果您想快速将其恢复,只需切换它——Ctrl-Alt-L——这将显示日志中的所有行,而那些被排除的行将显示为灰色。

在上例中,我排除了所有以 Installation Failure 开头的行。

跳转到行/时间

另一种导航日志的方式是跳转到特定行或日期/时间。只需按 Ctrl-G(跳转到)。

Go to 功能有两种方式:

  • 跳转到精确的行或日期/时间,或者
  • 跳转到偏移的行或日期/时间——只需加上 + 或 - 前缀,这就是一个偏移量。

对话框非常直观,并且可以处理大量的日期/时间格式。它还会实时显示将要跳转到的位置。例如:

  • -2.5d 将显示一个提示,如“Before 216000 secs”(2.5 天前),
  • 11/20 将显示“To Date 2016/11/20 00:00:00.000”
  • 11/19 2:4 将显示“To Date 2016/11/19 02:04:00.000”
  • +10h 将显示“After 36000 secs”(10 小时后)

实时更新

您已选择要打开的 Windows 事件日志,并且现在正在愉快地查看它们。

当新事件被记录到您打开的任何日志中时,您将实时看到它们。它会自动刷新。

如果您碰巧在第一行(因为对于 Windows 事件日志,默认显示最新条目),您将自动滚动到新条目。

打开日志历史记录

Log Wizard 很智能,并且会记住一切。您的切换设置、窗口位置、过滤器等。它记住的事情中还包括:上次打开的日志历史记录。

默认情况下,当您启动 Log Wizard 时,它会自动重新打开您上次打开的日志。您可以在 Preferences (Ctrl-P) 中关闭此功能——Automatically Open Last Log On Restart

假设您关闭了 Automatically Open Last Log On,那么每次都不需要调用 Actions >> Open Log 来重新打开上次打开的 Windows 事件日志。只需转到 Actions >> Show History,或按 Ctrl-H,然后选择上次的日志。

默认情况下,Last Log 实际上是已选中的,因此为了更快地操作,您可以将 Ctrl-H, Enter 视为重新打开上次日志的快捷方式。

调试器视图

顺便说一句,Log Wizard 除了 Windows 事件日志和文件之外,还可以监视调试器视图条目——这只是应用程序使用 OutputDebugString 写入的任何内容。或者,对于 C# 用户来说,任何使用 Debug.Write[Line]Trace.Write[Line] 编写的内容。所以,例如,它可以捕获这个:

static void Main() {
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    Debug.WriteLine("debug - this is the beginning");
    Trace.WriteLine("trace - this is the beginning");
    Application.Run(new Form1());
    Trace.WriteLine("this is the end");
}

打开新日志时——Ctrl-O 或 Actions >> Open Log,选择 Debug Viewer。您会看到这个:

您可以按应用程序名称过滤事件,或显示所有事件(取决于您运行的应用程序,这可能会变得相当拥挤)。假设您的应用程序名为 Windowsformsapplication1,只需在此处输入(不区分大小写),然后按 OK。运行您的应用程序。您将看到类似以下内容:

非常酷。 ;)

您想要什么?

创建(并优化)一个 Windows 事件日志查看器,我必须承认,比我最初预期的要困难得多。不过,这还是很有趣的。

您希望从这样的日志查看器中获得什么?您最喜欢的功能是什么?

如果它还没有在这里,我会尽力实现它。

  • 请在下方的评论中留下您的想法,或者
  • github 上添加一个问题

高级:为什么事件到达需要这么长时间?

当您打开事件查看器并打开事件日志时,它很快。但当您从外部应用程序查看同一个日志时,事情就慢多了。为什么呢?

如果您在 Google 上搜索 .NET 中读取事件日志,您会发现人们对此抱怨很多。微软似乎并不在意。所以您实际上只有两个选择:

  • 结果快速,但 UI 非常糟糕(事件查看器)
  • 结果较慢,但您可以选择如何显示它们,从而拥有一个更好的 UI。

如果您想在事件查看器之外查询 Windows 事件日志,您有两个选择:

  • 使用非常底层的 API(Win32 API - Event Log ReferenceExample)。如果您查看示例,您就会明白我为什么避免它。
  • 使用高级且易于使用的 .NET API。它的速度慢了几倍。

所以我选择了后者。为什么它这么慢?我不知道——我可以告诉您瓶颈在哪里,其余的只是我的猜测。

使用 .NET API 之一,您可以查询 Windows 事件日志(使用 XPATH 查询),然后处理每个记录。

遍历查询速度很快。枚举其一些重要属性是瓶颈:

  • 获取事件的 Category (EventRecord.TaskDisplayName)
  • 获取 Message 本身(EventRecord.FormatDescription()

FormatDescription() 非常慢——在我(非常快的)机器上——每次大约需要 2-3 毫秒。

您应该知道,许多 EventRecord 属性/方法会引发大量异常。我猜测是因为底层代码会检查用户凭据(用户是否允许实际查看事件?)。

例如,如果您的 Windows 帐户不属于“Event Log Readers”用户组,读取日志的速度会**慢得多**。

引发异常的成本非常高——有时是2000 倍甚至更高(参见这里这里)——并且在读取事件详细信息时,您可能会遇到不止一个异常。

我的个人看法是,EventRecord 类实现得非常糟糕——首先,应该有一种方法可以在不引发任何异常的情况下调用其方法/属性。

但更糟糕的是,在 FormatDescription() 中,似乎有一个全局(互斥锁)——这样就没有两个线程可以访问两个不同 EventRecord 的描述。我尝试使用 Parallel.For 来读取 5000 个事件的详细信息。令我惊讶的是,代码执行的时间与使用单线程读取这些事件的时间相同,唯一的区别是使用 Parallel.For 实际上使用了接近 100% 的 CPU(我的 8 个逻辑 CPU),而在单线程上运行时,CPU 使用率大约为 6-8%。

避免 FormatDescription() 几乎是不可能的——但如果您知道有什么方法,请告诉我。

历史

  • 2016 年 1 月 21 日,初始版本(1.7)
© . All rights reserved.