使用 Get-WinEvent PowerShell Cmdlet 的完整指南

Windows有几种不同的事件日志,但如何快速检索它们?Get-WinEvent cmdlet可以检索经典的Windows事件日志,如系统和应用程序日志,由Windows事件日志技术生成的日志,甚至是Windows事件跟踪(ETW)日志!

在本文中,了解如何利用Get-WinEvent从事件日志中检索和过滤事件!

先决条件

要跟着做,您只需要当前版本的Windows 10和PowerShell 5.1及更高版本。本文使用的是Windows 10和PowerShell 7.1。

使用Get-WinEvent列出可用日志

不知道可能需要哪些日志条目,而不知道所有可用日志。使用Get-WinEvent,您可以使用-ListLog参数快速列出所有可用日志。 *参数值告诉Get-WinEvent列出所有日志而不进行过滤。如下所示,检索到所有日志,但仅使用Select-Object cmdlet显示了有限的属性。

Get-WinEvent -ListLog * | Select-Object LogName, RecordCount, IsClassicLog, IsEnabled, LogMode, LogType | Format-Table -AutoSize

默认情况下,并非所有日志都已启用。您可能需要打开事件查看器,定位日志,然后右键单击启用日志以显示事件。

Listing all available event logs.

所有 Windows Vista 后的日志保存为 *.evtx 文件,而不是较旧的 *.evt 格式。属性 IsClassicLog 表明日志事件是在 消息文件*.mc 格式)还是在 清单*.xml 格式)中定义的。

一个有趣的属性是 LogMode,你可能注意到它通常设置为 Circular

  • Circular – 当日志满时覆盖最旧的日志条目。
  • Retain – 保留所有事件,直到日志满并停止记录,直到释放为止。
  • AutoBackup – 当日志满时自动备份和归档事件日志。
Highlighting the LogMode property.

最后,看一看属性 LogType,有几种不同类型的日志。这个属性更多地作为一个分类属性,但通常会告诉日志的使用方式和显示的事件类型。

  • 管理 – 主要用于最终用户和管理用户。
  • 分析 – 通常是高容量日志,用于描述程序操作。
  • 调试 – 用于需要深入了解程序内部的开发人员。
  • 操作 – 在操作过程中发生的事件,有助于诊断事件发生并触发进程。
Highlighting the LogType property.

列出事件日志提供者

现在您已经对不同日志及其属性有了清晰的理解,有助于理解事件日志提供者是什么。 在事件日志术语中,提供者是事件的来源。

事件日志提供者是唯一的,与每个日志(例如应用程序或系统日志)相关联,并将作为事件起源的命名来源。

也许您希望在过滤日志时找到问题,并且可能只对特定提供者的问题感兴趣。 要列出可用的提供者,请使用-ListProvider参数。 如下所示,*列出所有可用的提供者以及提供者与何种日志相关联,例如 Windows PowerShell 或系统。

Get-WinEvent -ListProvider * | Format-Table -Autosize
Listing event log providers.

也许你只想列出特定日志(例如System)可用的提供者。要做到这一点,你可以使用LogLinks属性的值来过滤事件,使用Where-Object命令进行筛选。 LogLinks属性显示链接的事件日志列表。

要使用Where-Object过滤请求的日志,使用-In比较运算符只过滤具有LogLinks属性值中包含System的事件。 最后,使用Format-Table -AutoSize使输出更易读,如下所示。

Get-WinEvent -ListProvider * | Where-Object { 'System' -In ($_ | Select-Object -ExpandProperty Loglinks | Select-Object -ExpandProperty Logname) } | Format-Table -AutoSize
Filtering event log providers to a specific log.

使用Get-WinEvent检索经典事件日志

解决Windows问题的第一步是检索应用程序日志或系统日志,这恰好是经典事件日志。在下面的示例中,你将使用应用程序事件日志的-MaxEvents参数检索前100个事件。

为了更容易阅读结果,请仅选择读取条目所需的属性。否则,条目将按提供者名称分组,这会使解析结果列表变得困难。

Get-WinEvent -LogName 'Application' -MaxEvents 100 | Select-Object TimeCreated, ID, ProviderName, LevelDisplayName, Message | Format-Table -AutoSize
Returning events from the Application log.

寻找现代Windows事件使用Get-WinEvent

现在您已经从经典的应用程序日志中检索到了事件,那么从更新的Windows事件日志(例如Microsoft-Windows-WindowsUpdateClient/Operational)中获取结果呢?

与经典事件日志(例如System)不同,Microsoft-Windows-WindowsUpdateClient/Operational是一个现代日志,使用Get-WinEvent的方式与下面相同。

Get-WinEvent -LogName 'Microsoft-Windows-WindowsUpdateClient/Operational' -MaxEvents 10 | Select-Object TimeCreated, ID, ProviderName, LevelDisplayName, Message | Format-Table -AutoSize
Returning Windows Event Log records.

那么,如何仅获取最旧的事件呢?虽然您可以使用Sort-Object反转结果的顺序,但是请使用-Oldest参数检索前10个事件,如下所示。

Get-WinEvent命令会为您进行过滤,而不是返回所有结果并进行排序,这通常较慢。

Get-WinEvent -LogName 'Microsoft-Windows-WindowsUpdateClient/Operational' -Oldest -MaxEvents 10 | Select-Object TimeCreated, ID, ProviderName, LevelDisplayName, Message | Format-Table -AutoSize
Returning only the oldest events in a Windows Event Log.

使用Get-WinEvent检索Windows事件跟踪(ETW)文件

也许您有来自另一台计算机的导出的*.evtx文件,或者已备份了现有的日志。您可以使用Get-WinEvent cmdlet读取这些日志。如果需要出于审计目的保留日志,Get-WinEvent是在脚本中快速查询这些日志的标准cmdlet的好方法。

为了演示从一个*.evtx文件中检索日志条目,您需要一个导出的日志文件。

1. 打开事件查看器并导航到一个日志。在本示例中,选择应用程序和服务日志 → Windows PowerShell日志。

Navigate to a Windows Event Viewer log.

2. 接下来,在操作窗格中单击另存所有事件为…菜单项。

Save the log file.

3. 将文件保存到磁盘位置,以便通过Get-WinEvent命令检索。

Choose a location to save the log file.

现在,您已经导出了一个日志文件,通过-Path参数传递日志文件位置以读取事件。在下面示例中,导出了Windows PowerShell日志以供以后使用。

Get-WinEvent -Path 'C:\Articles\WindowsPowerShell.evtx' -MaxEvents 10 | Select-Object TimeCreated, ID, ProviderName, LevelDisplayName, Message | Format-Table -AutoSize
Retrieving specific events from the exported event file.

使用Get-WinEvent过滤Windows事件日志

虽然您可以使用标准的Where-Object cmdlet过滤日志,但Get-WinEvent提供了内置过滤器。通过返回所有结果然后进行过滤,比必要的工作要多。相反,您应该尽可能在源头尝试尽可能多地过滤。

Get-WinEvent cmdlet提供了三个参数来帮助您过滤数千个事件,称为-FilterHashTable-FilterXPath-FilterXML。每个参数通常执行相同的任务,只是以不同的方式。

使用FilterHashTable过滤事件日志

参数-FilterHashTable根据匹配的属性(如LogName)过滤内容。您可以使用哈希表来过滤,而不是使用-LogName参数来按特定日志进行过滤,比如@{'LogName' = 'Application'},它对应于LogName事件属性。

下面的示例提供了一个哈希表给-FilterHashTable参数,该参数仅查找Application日志,并且开始时间为当天午夜后的所有事件,Get-WinEvent会快速返回结果。

Get-WinEvent -FilterHashTable @{'LogName' = 'Application'; 'StartTime' = (Get-Date -Hour 0 -Minute 0 -Second 0)} | Select-Object TimeCreated, ID, ProviderName, LevelDisplayName, Message | Format-Table -AutoSize
Filtering events with the FilterHashTable parameter.

比较上面相同命令的过滤速度,一个是通过流水线上的-FilterHashTable参数进行过滤,另一个是通过Where-Object进行过滤。您会发现,使用Where-Object的命令比使用-FilterHashTable参数的命令要慢得多。

Comparing filtering with FilterHashTable and Where-Object.

使用FilterXPath参数过滤事件日志

事件日志条目存储为XML文件,因此您可以使用XPath语言,一种XML查询语言,来过滤日志条目。执行上述相同命令并转换为XPath,您可以达到相同的结果。

要创建XPath查询,请使用Windows事件查看器中的过滤功能,如下所示。

1. 打开事件查看器并导航到日志,例如Windows日志→应用程序日志。

Opening the Windows Event Viewer.

2. 接下来,在右侧窗格中点击“筛选当前日志”链接。

Choosing to Filter the Current Log.

3. 输入您想要用来过滤日志的参数。

Creating a filter for the current log.

4. 点击 XML 选项卡并复制包含在选择标签内的部分。

Copying the XPath command.

5. 现在,使用 -FilterXPath 参数复制并粘贴已复制的内容。您现在可以看到,使用事件日志查看器中找到的 XPath 语法,可以构建一个仅过滤必要信息的查询。

Get-WinEvent -LogName 'Application' -FilterXPath "*[System[(Level=1  or Level=3)]]" | Select-Object TimeCreated, ID, ProviderName, LevelDisplayName, Message | Format-Table -AutoSize
Demonstrating the use of the FilterXPath parameter.

深入讨论如何制作 XPath 查询超出了本文的范围,但基本格式如下所示。当 FilterXPath 参数过滤日期时,您会看到一个重要区别:您需要使用更具体的日期格式,yyyy-MM-ddTHH:mm:ss.fffZ,并且日期必须以 UTC 返回,这由 -AsUTC 开关标识。

Get-WinEvent -LogName 'Application' -FilterXPath "*[System[TimeCreated[@SystemTime >= '$(Get-Date -Hour 0 -Minute 0 -Second 0 -Millisecond 0 -Format "yyyy-MM-ddTHH:mm:ss.fffZ" -AsUTC)']]]" | Select-Object TimeCreated, ID, ProviderName, LevelDisplayName, Message | Format-Table -AutoSize
Filtering events using XPath.

使用 FilterXML 过滤事件日志结果。

最后,可用的最后一个过滤参数是 -FilterXML 参数。与 -FilterXPath-FilterHashTable 参数不同,此参数接受 XML,然后用于过滤事件。-FilterXML 参数允许更复杂的规则,并且如下所示,可以复制先前的过滤示例。

正如前面的示例所示,您可以从事件查看器 → 过滤当前日志功能中检索预格式化的查询。而不仅仅是选择Select节点中的内容,您将使用整个查询。如Select节点中的*所示,并没有实际选择任何过滤器。这将为下一个示例提供一般的标记。

Selecting the entire XML query from Filter Current Log in the Event Viewer.

与创建单行命令不同,首先,将XML查询分开并将标记分配给变量$Query,如下例所示。将查询分配给变量可提高易用性和可读性。接下来,将$Query变量传递给Get-WinEvent-FilterXML参数。

如下所示,您将看到更复杂查询的结果,返回当天的所有事件并存储在Application日志中。

$Query = "<QueryList>
  <Query Id='0' Path='Application'>
    <Select Path='Application'>*[System[TimeCreated[@SystemTime >= '$(Get-Date -Hour 0 -Minute 0 -Second 0 -Millisecond 0 -Format "yyyy-MM-ddTHH:mm:ss.fffZ" -AsUTC)']]]</Select>
  </Query>
</QueryList>"

Get-WinEvent -FilterXML $Query | Select-Object TimeCreated, ID, ProviderName, LevelDisplayName, Message | Format-Table -AutoSize
Showing how FilterXML works.

结论

Get-WinEvent cmdlet可快速查询多个事件日志源,具有强大的过滤能力。从审计到问题解决,Get-WinEvent cmdlet是任何系统管理员工具包中的重要补充!

Source:
https://adamtheautomator.com/get-winevent/