March 7th, 2011

Use PowerShell to Query All Event Logs for Recent Events

Summary: Learn how to use Windows PowerShell to easily query all event logs for recent events.

It is raining outside in Seattle, Washington. I suppose that might not be news to most people, but then I am not from Seattle. In fact, the last time I was out here to teach a Windows PowerShell class to a group of Microsoft network engineers, it was beautiful, sunny, and a bit cool. The sky was a deep blue. One of my students told me that it is always like that here in Seattle, and that the reputation for rain is something they only perpetuate to keep the tourists away. Alas, it seems that is not necessarily the case.

The Scripting Wife and I are out here for two reasons. The first reason is the Microsoft MVP Summit that has been going on all week. The second is for me to teach a Windows PowerShell class to another group of Microsoft engineers. Both reasons are excellent reasons to jump into a plane and fly to Seattle. Besides, I was getting tired of the sunny weather back in Charlotte, North Carolina. I mean, my next-door neighbor was mowing his grass. Give me cold, cloudy, rainy weather any time if it means not mowing the grass.

This has made for an all Windows PowerShell all the time kind of week. It began with breakfast with Microsoft MVPs, Kirk Munro and Shane Hoey, and it ended with me teaching a four-day class. In the intervening time, there was a Scripting Guys booth at the TechNet/MSDN open house, and various evening events with the product group and MVPs. It has been a tremendously invigorating week. Everywhere I went people were talking about Windows PowerShell.

On the first day of class, I began by explaining that Windows PowerShell is both an interactive console and a scripting language. In the purest sense, a Windows PowerShell script is simply a collection of Windows PowerShell commands that one saves with a .ps1 file extension. In this regard, there is absolutely no difference between typing commands interactively and saving the same commands in a file. In fact, on many occasions, my Windows PowerShell commands morph into a Windows PowerShell command.

I showed the class an example of using the Get-WinEvent Windows PowerShell cmdlet. The command to list all of the classic event logs and the ETL diagnostic logs are shown here.

Get-WinEvent -ListLog * -EA silentlycontinue

The output from the above command is shown in the following image.

Image of command output

After I have a listing of all of the logs, both classic and ETL, I can use the list and query all of the logs’ recent entries. When I showed the class the command that is shown here, I was nearly awarded a standing ovation.

Get-WinEvent -ListLog * -EA silentlycontinue |

where-object { $_.recordcount -AND $_.lastwritetime -gt [datetime]::today} |

Foreach-Object { get-winevent -LogName $_.logname -MaxEvents 1 }

In this code, the Get-WinEvent cmdlet retrieves all of the event logs. The EA is an alias for the ErrorAction parameter. The value SilentlyContinue for the ErrorAction parameter tells Windows PowerShell to hide any non-terminating errors and to continue processing commands. This causes Windows PowerShell to skip any logs that my currently logged on, non-elevated profile does not have access to read. The Where-Object cmdlet receives the resulting collection of event logs via the Windows PowerShell pipeline. The filter used for the Where-Object cmdlet looks for event logs that have at least one event contained in the log ($_.recordcount). In addition, (-AND) the filter looks for a lastwritetime property that is greater than (-gt) midnight today ([datetime]::today). The Foreach-Object cmdlet processes the collection of event logs that have records written today, by retrieving the most recent event from the log. The output from the previous command is shown in the following image.

Image of command output

The previous command, although interesting, is not extremely informative because the provider name is truncated, as is the actual event message. To combat these twin problems, I modified the command by sending it to the Format-Table cmdlet. The revised command is shown here.

Get-WinEvent -ListLog * -EA silentlycontinue |

where-object { $_.recordcount -AND $_.lastwritetime -gt [datetime]::today} |

foreach-object { get-winevent -LogName $_.logname -MaxEvents 1 } |

Format-Table TimeCreated, ID, ProviderName, Message -AutoSize –Wrap

When I ran this command for the class, there were audible cheers. The results from the “award winning” command are shown here.

Image of command output

By experimenting with this code, one can quickly create a customized solution to enable efficient processing of event log data. Additionally, the ComputerName parameter permits easy access to event logs on remote machines.

This is one reason I love teaching Windows PowerShell classes—simple solutions arise to previously vexatious problems.

Well, I need to get back to class—I just wanted to share this with you. Have an awesome day.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

Author

1 comment

Discussion is closed. Login to edit/delete existing comments.

  • J S

    There seems to a be a 256 logname limit piping to get-winevent again. Get-winevent also gets upset if you pipe it to select -first 256 directly and cut the pipe when it has enough.

    get-winevent -listlog * | select -first 256

    get-winevent : Could not retrieve information about the Microsoft-Windows-PrintBRM/Admin log. Error: The pipeline has been stopped..
    At line:1 char:1
    + get-winevent -listlog * | select -first 256 | more
    + ~~~~~~~~~~~~~~~~~~~~~~~
    ...

    Read more