Zam
Zam

Reputation: 1388

Event Log query with Get-WinEvent / Get-EventLog is very slow when querying shutdown event 1074

I'm writing a PowerShell script that needs to be able to get the query the System Event Log and find events with the Event ID 1074 which indicates a shutdown.

To do this, I was using the following code, however, I've taken notice that when running the code on servers with larger System Event Logs, the command takes many seconds to complete.

Get-WinEvent -LogName 'System' | Where-Object { $_.Id -eq 1074 }

Is there a way to improve the performance of this code?

Upvotes: 4

Views: 7802

Answers (1)

Zam
Zam

Reputation: 1388

Get-WinEvent vs Get-EventLog

The first performance boost you can get is using Get-WinEvent over Get-EventLog. That is because Get-WinEvent is replacing Get-EventLog and is supposed to perform better.

Correctly filtering the query

I found a fantastic article by Ed Wilson which goes into great detail how you can improve the performance of a query such as the one I've posted above. I will highlight the performance tweaks I made to greatly improve the performance of my script.

  1. Don't use the -LogName parameter, but rather, use the appropriate -ProviderName of the provider that generates the event you're looking for (Ed's blog post goes into detail of how to find this). In my case, I needed to use the User32 provider since that's the provider that generates the 1074 event I'm interested in.
  2. Avoid full traversals of data if at all possible. You'll notice my script had a Where-Object clause. This clause would iterate over ever event piped into it looking for only the ones that have the 1074 Id. To avoid this, Get-WinEvent has a -FilterHashtable parameter which can be used to filter your query results within the Get-WinEvent cmdlet, improving efficiency. As quoted in the Microsoft documentation: "When you work with large event logs, it's not efficient to send objects down the pipeline to a Where-Object command."

The code

I've implemented the aforementioned concepts and timed the improvements for each to show the difference in performance using the Measure-Command cmdlet with the -Expression parameter. Note that the machine that I'm testing on has 23,581 events in the System log.

Baseline

Measure-Command -Expression {
    Get-WinEvent -LogName 'System' | Where-Object { $_.Id -eq 1074 }
}

# TotalSeconds      : 7.600536

Using ProviderName vs LogName

Measure-Command -Expression {
    Get-WinEvent -ProviderName 'User32' | Where-Object { $_.Id -eq 1074 }
}

# TotalSeconds      : 0.1929325

Using FilterHashtable

Measure-Command -Expression {
    Get-WinEvent -FilterHashtable @{ProviderName = "User32"; Id = 1074} 
}

# TotalSeconds      : 0.1578928

Upvotes: 9

Related Questions