A Complete Guide to Using the Get-WinEvent PowerShell Cmdlet

Adam Listek

Read more posts by this author.

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.

Listing all available event logs.
Listing all available event logs.

All logs post-Windows Vista save as *.evtx files instead of an older *.evt format. The property IsClassicLog 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.
Highlighting the LogMode property.
Highlighting the LogMode property.

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.
Highlighting the LogType property.
Highlighting the LogType property.

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
Listing event log providers.
Listing event log providers.

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
Filtering event log providers to a specific log.
Filtering event log providers to a specific log.

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
Returning events from the Application log.
Returning events from the Application log.

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
Returning Windows Event Log records.
Returning Windows Event Log records.

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
Returning only the oldest events in a Windows Event Log.
Returning only the oldest events in a Windows Event Log.

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.

Navigate to a Windows Event Viewer log.
Navigate to a Windows Event Viewer log.

2. Next, click on the Save All Events As… menu item in the Actions pane.

Save the log file.
Save the log file.

3. Save the file to a disk location to be retrieved by the Get-WinEvent command.

Choose a location to save the log file.
Choose a location to save the log file.

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
Retrieving specific events from the exported event file.
Retrieving specific events from the exported event file.

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
Filtering events with the FilterHashTable parameter.
Filtering events with the FilterHashTable parameter.

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.

Comparing filtering with FilterHashTable and Where-Object.
Comparing filtering with FilterHashTable and Where-Object.

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.

Opening the Windows Event Viewer.
Opening the Windows Event Viewer.

2. Next, click on the Filter Current Log link in the right-hand pane.

Choosing to Filter the Current Log.
Choosing to Filter the Current Log.

3. Enter the parameters that you want to use to filter the log.

Creating a filter for the current log.
Creating a filter for the current log.

4. Click on the XML tab and copy the section contained within the Select tag.

Copying the XPath command.
Copying the XPath command.

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
Demonstrating the use of the FilterXPath parameter.
Demonstrating the use of the FilterXPath parameter.

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 events using XPath.
Filtering events using XPath.

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.

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

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
Showing how FilterXML works.
Showing how FilterXML works.

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!

Subscribe to Stay in Touch

Never miss out on your favorite ATA posts and our latest announcements!

Looks like you're offline!