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

Windows 有多個不同的事件記錄,但要快速擷取它們,應該如何操作呢?Get-WinEvent 指令可以擷取經典的 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 指令顯示有限的屬性

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。為此,您可以使用Where-Object命令,使用LogLinks屬性的值篩選事件。 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' = 'Application'})來篩選特定日誌,而不是使用 -LogName 參數,這對應於 LogName 事件屬性。

下面的示例提供了一個哈希表給 -FilterHashTable 參數,該哈希表僅查找應用程式日誌以及從當天午夜後的所有事件開始的事件,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 標籤並複製在 Select 標籤中包含的部分。

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/