Windows has several different event logs, but how do you go about retrieving them quickly? The Get-WinEvent
cmdlet can retrieve classic Windows event logs like the System and Application logs, logs generated by Windows Event Log technology, and even Event Tracing for Windows (ETW) logs!
In this article, learn how to leverage Get-WinEvent
to retrieve and filter events from event logs!
Prerequisites
To follow along, you only need a current version of Windows 10 and PowerShell 5.1 and greater. This article is using Windows 10 and PowerShell 7.1.
Listing Available Logs with Get-WinEvent
It’s hard to know what log entries you may need without knowing all the available logs. With Get-WinEvent
, you can list all available logs quickly using the -ListLog
parameter. The *
parameter value tells Get-WinEvent
to list all logs without filtering. As shown below, all logs are retrieved, but only a limited set of properties are shown using the Select-Object
cmdlet.
Get-WinEvent -ListLog * | Select-Object LogName, RecordCount, IsClassicLog, IsEnabled, LogMode, LogType | Format-Table -AutoSize
Not all logs are enabled by default. You may need to open Event Viewer, locate the log, and right-click to Enable the log before events show.
All logs post-Windows Vista save as
*.evtx
files instead of an older*.evt
format. The propertyIsClassicLog
states whether the log events are defined in a Message File,*.mc
, format or in a manifest,*.xml
, format.
An interesting property is the LogMode
, which you may have noticed is usually set to Circular
.
Circular
– Overwrite the oldest log entry once full.Retain
– Keep all events until the log is full and stop logging until freed.AutoBackup
– Automatically back up and archive event logs once full.
Finally, looking at the LogType
property, there are several different types of logs. This property serves more as a categorization property, but it typically informs how the log is used and the types of events shown.
- Administrative – Primarily intended for end-users and administrative users.
- Analytical – Typically, a high volume log, meant to describe program operations.
- Debug – Meant for developers needing a deep-dive into program internals.
- Operational – An event that occurs during operation and is useful to diagnose occurrences and trigger processes.
Listing Event Log Providers
Now that you have a solid understanding of the different logs and their properties, it helps to understand what an Event Log Provider is. A provider, in Event Log terminology, is a source of an event.
Event log providers are unique and linked to each log, such as Application or System logs, and will serve as the named source where an event originates.
Perhaps you’d like to find issues when filtering logs, and you may only be interested in issues of a particular provider. To list what providers are available, use the -ListProvider
parameter. As shown below, the *
lists all providers available and what log’s the providers are linked against, such as Windows PowerShell or System.
Get-WinEvent -ListProvider * | Format-Table -Autosize
Perhaps you may want only to list providers available to a particular log, such as System
. To do so, you could filter events using the Where-Object
command using values of the LogLinks
property. The LogLinks
property shows the linked event logs as a list.
To filter the requested logs with Where-Object
, use the -In
comparison operator to filter only those events with System
in the LogLinks
property value. Finally, the use of Format-Table -AutoSize
makes reading the output easier, as shown below.
Get-WinEvent -ListProvider * | Where-Object { 'System' -In ($_ | Select-Object -ExpandProperty Loglinks | Select-Object -ExpandProperty Logname) } | Format-Table -AutoSize
Retrieving Classic Event Logs with Get-WinEvent
The first step in troubleshooting a Windows problem is retrieving either the Application or System log, which happens to be Classic Event Logs. In the example shown below, you will retrieve the first 100
events using the -MaxEvents
parameter of the Application event log.
To make reading the results easier, select just the properties needed to read the entries easier. Otherwise, the entries are grouped by the provider name, which makes parsing the list of results difficult.
Get-WinEvent -LogName 'Application' -MaxEvents 100 | Select-Object TimeCreated, ID, ProviderName, LevelDisplayName, Message | Format-Table -AutoSize
Finding Modern Windows Events with Get-WinEvent
Now that you have retrieved events from the classic Application log, what about results from a newer Windows Event Log, such as Microsoft-Windows-WindowsUpdateClient/Operational
?
Unlike a classic event log, such as System
, the Microsoft-Windows-WindowsUpdateClient/Operational
is a modern log, with Get-WinEvent
working the same as below.
Get-WinEvent -LogName 'Microsoft-Windows-WindowsUpdateClient/Operational' -MaxEvents 10 | Select-Object TimeCreated, ID, ProviderName, LevelDisplayName, Message | Format-Table -AutoSize
What about getting just the oldest events? Although you could reverse order the results with Sort-Object
, use the -Oldest
parameter to retrieve the first 10
events, as shown below.
The Get-WinEvent
command does the filtering for you instead of returning all results and sorting, which is typically slower.
Get-WinEvent -LogName 'Microsoft-Windows-WindowsUpdateClient/Operational' -Oldest -MaxEvents 10 | Select-Object TimeCreated, ID, ProviderName, LevelDisplayName, Message | Format-Table -AutoSize
Retrieving Event Tracing for Windows (ETW) Files with Get-WinEvent
Perhaps you have an exported *.evtx
file from another computer or haved backed up an existing log. You can read those logs with the Get-WinEvent
cmdlet. If you need to keep logs for auditing purposes, Get-WinEvent
is a great way to query those logs with standard cmdlets within scripts quickly.
To demonstrate retrieving log entries from a *.evtx
file, you need an exported log file.
1. Open the Event Viewer and navigate to a log. In this example, the Application and Services Logs → Windows PowerShell log.
2. Next, click on the Save All Events As… menu item in the Actions pane.
3. Save the file to a disk location to be retrieved by the Get-WinEvent
command.
Now that you have exported a log file pass the log file location via the -Path
parameter to read the events. In the example shown below, the Windows PowerShell log is exported for later consumption.
Get-WinEvent -Path 'C:\Articles\WindowsPowerShell.evtx' -MaxEvents 10 | Select-Object TimeCreated, ID, ProviderName, LevelDisplayName, Message | Format-Table -AutoSize
Filtering Windows Event Logs Using Get-WinEvent
Although you could filter logs with the standard Where-Object
cmdlet, Get-WinEvent
offers built-in filters. By returning all results and then filtering, more work is done than is necessary. Instead, you should always try to filter at the source as much as possible.
The Get-WinEvent
cmdlet provides three parameters to help you filter through thousands of events called -FilterHashTable
, -FilterXPath
, and -FilterXML
. Each parameter generally performs the same task just in a different way.
Filtering Event Logs with FilterHashTable
The -FilterHashTable
parameter filters content based on the matched properties, such as LogName
. Instead of using the -LogName
parameter to filter by a specific log, you can instead use a hash table, such as @{'LogName' = 'Application'}
, which would correspond to the LogName
event property.
The example shown below provides a hash table to the -FilterHashTable
parameter that looks for just the Application log and with a start time that is all events past midnight of the current day, Get-WinEvent
quickly returns results.
Get-WinEvent -FilterHashTable @{'LogName' = 'Application'; 'StartTime' = (Get-Date -Hour 0 -Minute 0 -Second 0)} | Select-Object TimeCreated, ID, ProviderName, LevelDisplayName, Message | Format-Table -AutoSize
Compare the filtering speeds of the same command above to one filtered from via Where-Object
instead of via the -FilterHashTable
parameter on the pipeline. As you can see, the command using Where-Object
is much slower than the one that uses the -FilterHashTable
parameter.
Filtering Event Logs Using the FilterXPath
Parameter
Event log entries are stored as XML files, and therefore you can use the XPath language, an XML querying language, to filter through the log entries. Performing the same command used above and translating to XPath, you can achieve the same results.
To craft an XPath query, use the filtering ability in the Windows Event Viewer, as shown below.
1. Open the Event Viewer and navigate to a log, such as the Windows Logs → Application log.
2. Next, click on the Filter Current Log link in the right-hand pane.
3. Enter the parameters that you want to use to filter the log.
4. Click on the XML tab and copy the section contained within the Select tag.
5. Now, copy and paste the copied content with the -FilterXPath
parameter. You can now see below that using the XPath syntax found from the event log viewer, you can build a query to filter only the information necessary.
Get-WinEvent -LogName 'Application' -FilterXPath "*[System[(Level=1 or Level=3)]]" | Select-Object TimeCreated, ID, ProviderName, LevelDisplayName, Message | Format-Table -AutoSize
Diving into how to craft XPath queries is out of scope for this article, but the basic format is shown below. When the FilterXPath
parameter filters a date, you’ll see one big difference: you need to use a more specific date format, yyyy-MM-ddTHH:mm:ss.fffZ
, that the date must be returned in UTC, which is noted by the -AsUTC
switch.
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 Event Log Results with FilterXML
Finally, the last filtering parameter available is the -FilterXML
parameter. Unlike the -FilterXPath
and -FilterHashTable
parameters, this parameter takes XML that is then used to filter the events. The -FilterXML
parameter allows for more complex rules, and as shown below, can replicate the previous filtering examples.
As shown in the previous example, you may retrieve a pre-formatted query from the Event Viewer → Filter Current Log ability. Instead of only selecting the content in the Select
node, you will use the entire query. There are no actual filters chosen, as noted by the *
in the Select
node. This will provide the general markup for the next example.
Instead of creating a one-line command, first, separate the XML query and assign the markup to a variable, $Query
, in the example below. Assigning the query to a variable makes for better ease of use and readability. Next, pass the $Query
variable to the -FilterXML
parameter of Get-WinEvent
.
As shown below, you see the results of the more complex query returning all events from that day and stored in the Application
log.
$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
Conclusion
The Get-WinEvent
cmdlet makes short work of querying multiple event log sources with powerful filtering abilities. From auditing to problem-solving, the Get-WinEvent
cmdlet is a crucial addition to any System Administrators’ toolkit!