Advanced Event Log Filtering Using PowerShell

In a previous blog post, Monitoring Event Logs with PowerShell, I showed you how to use Get-WinEvent to perform basic event log monitoring using PowerShell. In this article, I want to demonstrate how Get-WinEvent can be used to run more complex queries using the –FilterHashtable parameter.

Let’s start by returning the last 50 events in the System event log:

Get-WinEvent –LogName System –MaxEvents 50

As I mentioned in the previous blog post, Get-WinEvent allows filtering at source, so unlike Get-EventLog, we don’t need to pipe the results to the Where-Object cmdlet, which is less efficient especially when pulling logs across the network from remote devices. To create a simple filter, we can use the –FilterHashtable parameter:

Get-WinEvent –FilterHashtable @{logname='system'} –MaxEvents 50

The command above does nothing different from the first, other than we use –FilterHashtable instead of the –LogName parameter to specify the log name. We can add to the hash table and create a more complex filter to show only the last 50 error events:

Get-WinEvent –FilterHashtable @{logname='system'; level=2} –MaxEvents 50

Notice the event level must be specified as an integer, where 2 corresponds to the Error event level.

What is a hash table?

As you can see from the commands above, a hash table allows us to map keys to values. I.e. The logname key is mapped to ‘system’, and level to 2. In PowerShell, hash tables are often used as a means of specifying values in a command a more concise and readable form, without having to write a long set of parameters.

The –FilterHashtable parameter accepts the following key/value pairs:

1

Only the LogName and ProviderName keys accept wildcard input. You can also specify an array of integers for the Level key:

Get-WinEvent –FilterHashtable @{logname='system'; level=2,3} –MaxEvents 50

Here we get both Error and Warning level events. If you want to specify a start time, it’s best to define it in a variable first using the Get-Date and New-TimeSpan cmdlets. The $time variable defined below will show all events starting from yesterday, i.e. today’s date minus 24 hours.

$time = (Get-Date) - (New-TimeSpan -Day 1)

Get-WinEvent –FilterHashtable @{logname='system'; level=2; starttime=$time}

To expand the query further, I’m going to add some more key/value pairs to the hash table. Most of them, as listed in the table above, are self-explanatory; with the exception of Keywords, which as you see doesn’t accept a string input. I will explain how to use this key in a future post.

Get-WinEvent –FilterHashtable @{logname='system'; level=2; starttime=$time; id=20; providername=’Microsoft-Windows-WindowsUpdateClient’}

In the query above, I added the event ID and providername keys. To determine the value for the providername key, I used the Select-Object cmdlet to output the provider for each event:

Get-WinEvent –FilterHashtable @{logname='system'; level=2; starttime=$time; id=20} | Select-Object ProviderName

In this example, it just happens that all the returned events came from the same provider, but that might not necessarily be the case.