Use PowerShell to Parse Saved Event Logs for Errors

Use PowerShell to Parse Saved Event Logs for Errors

  • Comments 4
  • Likes

 

Summary: Simplify Windows auditing and monitoring by using Windows PowerShell to parse archived event logs for errors.

Hey, Scripting Guy! Question

Hey, Scripting Guy! I have been using a scheduled job and a Windows PowerShell script to archive our event logs to .evt files. When I need to check something, I need to import the .evtx file in to Event Viewer so that I can search the file. This is a bit cumbersome, and I would like to find a better way to do this. What I really wish is that I could query the .evtx file in the same way that I query a live event log. I think I can use LogParser to query the .evtx file, but I do not know what is up with that. It is more than six years old, and I hate to be dependent on something that is not in the operating system.

-- AH

Hey, Scripting Guy! Answer Hello AH,

Microsoft Scripting Guy Ed Wilson here. I have written Hey, Scripting Guy! Blog posts and a TechNet Magazine article about backing up event logs. However, until now, I have not written about parsing those event log files. By using the Get-WinEvent cmdlet, it is as easy to parse an archived event log file as it is to parse an online log.

To view the contents of an archived event log (it can be a .etl, .evt, or .evtx file), use the path parameter to point to the archived file. This is illustrated here:

PS C:\> Get-WinEvent -Path C:\fso\SavedAppLog.evtx

TimeCreated                      ProviderName                  Id            Message

-----------                             ------------                         --            -------

1/15/2011 9:09:11 AM       Outlook                            26           Connection to Microso...

1/15/2011 9:08:54 AM       Outlook                            26           Connection to Microso...

1/15/2011 9:05:46 AM       Office Software Prote...    1003       The Software Protecti...

1/15/2011 9:04:51 AM       Office Software Prote...    1003        The Software Protecti...

1/15/2011 8:37:59 AM       SceCli                                1704       Security policy in th...

<Truncated Output>

If I need to filter out the content of the saved file, I will need to use the FilterHashTable parameter. The FilterHashTable parameter was discussed yesterday.

This can be a bit confusing. The use of the Path and FilterHashTable are exclusive. This is shown in the two command sets:

Get-WinEvent [-Path] <string[]> [-ComputerName <string>] [-Credential <PSCredential>] [-FilterX

Path <string>] [-Force <switch>] [-MaxEvents <int64>] [-Oldest] [<CommonParameters>]

Get-WinEvent -FilterHashTable <Hashtable[]> [-ComputerName <string>] [-Credential <PSCredential

>] [-Force <switch>] [-MaxEvents <int64>] [-Oldest] [<CommonParameters>]

When I use the FilterHashTable parameter, I need to specify the provider, log, and other information via the hash table itself. To retrieve only Outlook event log entries from my saved application log, I specify the path to the log and the ProviderName key values in the hash table. Because the saved log is an application event log, I do not need to specify a value for the LogName key. The path to the saved log is the location (including the file name) of the stored log. The ProviderName key is the source of the events. The following command lists all events from the Outlook provider on my computer.

PS C:\> Get-WinEvent -FilterHashtable @{Path="C:\fso\SavedAppLog.evtx";ProviderName="outlook"}

TimeCreated                        ProviderName                       Id           Message

-----------                               ------------                              --           ------

1/15/2011 9:09:11 AM         Outlook                                 26         Connection to Microso...

1/15/2011 9:08:54 AM         Outlook                                 26         Connection to Microso...

1/15/2011 8:28:00 AM         Outlook                                 45         Outlook loaded the fo...

1/14/2011 11:28:43 PM       Outlook                                 45         Outlook loaded the fo...

1/14/2011 10:49:24 PM       Outlook                                 54         An appointment has be...

<Output Truncated>

In the event log entry shown in the following image, it quickly becomes obvious that the key values required for the FilterHashTable parameter and the values that show up in the graphical user interface do not match up.

Image of event log entry

When working with the Get-WinEvent Windows PowerShell cmdlet, I often find it helpful to consult the XML view of the event details. This view appears to have a bit more relevance. For example, I can tell that the Level: Information of the event log entry (seen in the figure above) is the same as the level 4 that is displayed in the XML view shown in the following image.

Image of XML view of event details

By consulting and matching the information, I compiled the table that follows to aid me in using the Get-WinEvent Windows PowerShell cmdlet FilterHashTable key values.

Event log viewer name

FilterHashTable parameter key name

Log Name

LogName

Source

ProviderName

Event ID

ID

Level

Level

User

UserID

Op Code

*

Logged

*

Task Category

*

Keywords

*

Computer

N/A use –ComputerName parameter

Details

Data

If I want to search for data that shows up in the Details portion of the Event properties, I must include the entire string, typed exactly as it appears. This is because the Data portion of the FilterHashTable does not accept a wildcard character. Therefore, the command shown here will retrieve all of the Outlook events that have the message that states that “Connection to Microsoft Exchange has been lost. Outlook will restore the connection when possible.”

PS C:\> Get-WinEvent -FilterHashtable @{Path="C:\fso\SavedAppLog.evtx";ProviderName="outlook";Data="

Connection to Microsoft Exchange has been lost. Outlook will restore the connection when possible."}

TimeCreated                         ProviderName     Id        Message

-----------                                ------------            --        -------

1/15/2011 9:08:54 AM          Outlook               26      Connection to Microso...

1/7/2011 3:46:52 PM            Outlook               26      Connection to Microso...

12/21/2010 11:36:31 AM      Outlook               26      Connection to Microso...

I can search for only event ID 26, as shown here, but the problem is that event ID 26 includes not only the connection lost but also the connection restored message detail.

PS C:\> Get-WinEvent -FilterHashtable @{Path="C:\fso\SavedAppLog.evtx";ProviderName="outlook";Id=26}

TimeCreated                          ProviderName     Id       Message

----------- -                              -----------              --        -------

1/15/2011 9:09:11 AM           Outlook               26      Connection to Microso...

1/15/2011 9:08:54 AM           Outlook               26      Connection to Microso...

1/7/2011 3:48:13 PM             Outlook               26      Connection to Microso...

1/7/2011 3:46:52 PM             Outlook               26      Connection to Microso...

12/21/2010 11:36:39 AM       Outlook               26      Connection to Microso...

12/21/2010 11:36:31 AM       Outlook               26      Connection to Microso...

<Output Truncated>

This particular view into the event log is not too bad, because I can easily tell that my connection to the Microsoft Exchange Server lost connection on 1/7/2011 for a minute and 21 seconds (by subtracting the amount of time between connection lost and connection restored).

If I want to determine the total number of disconnections during the course of my event log, I can pipe the results to the Measure-Object cmdlet and divide the number by two (to account for connection lost and restored—not precise, but better than typing out the entire text of the detail message).

PS C:\> $count = Get-WinEvent -FilterHashtable @{Path="C:\fso\SavedAppLog.evtx";ProviderName="outloo

k";Id=26} | Measure-object

PS C:\> $count.Count / 2

131.5

PS C:\>

From looking at the above data, I can also surmise that one day, I lost connection and it was never restored. If I really cared, I could parse the data further to discover when that date occurred.

In the ParseSavedEventLogsForErrors.ps1 script, I use the Get-ChildItem cmdlet to retrieve all the saved event logs from a central location. I then use the Get-WinEvent Windows PowerShell cmdlet to examine each saved log to look for errors in the log that occur between January 14, 2011, and January 15, 2011. This is an example of the type of script one might use to quickly peruse archived daily event logs.

ParseSavedEventLogsForErrors.ps1

Get-ChildItem -include *.evt,*.evtx -Path c:\fso -recurse |

ForEach-Object {

"Parsing $($_.fullname)`r`n"

Try

{ Get-WinEvent -FilterHashtable @{

Path=$_.fullname

Level=2;

StartTime="1/14/2011" ;

EndTime="1/15/2011"} -EA Stop}

Catch [System.Exception] {"No errors in current log"}

}

As the script currently stands, the script does not accept input parameters for the start time and end time or for the path to the stored logs, but that is an easy change to make. The Try/Catch block is required because an error is generated when an event log does not return any matching records. It is a non-terminating error, however, so I needed to specify the ErrorAction (EA is the parameter alias) of stop to cause the script to move into the catch block.

When the script runs, the output that is shown in the following image appears on my computer.

Image of script output

AH, that is all there is to using the Windows PowerShell Get-WinEvent cmdlet to query offline event logs. Neglected Windows PowerShell Cmdlet Week will continue tomorrow.

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 them on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

 

Ed Wilson, Microsoft Scripting Guy

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Awesome post again... thanks!  Mostly due to the eerie timing on the topic with a project I've been working on, but your notes helped to correlate the FilterHashtable and the XML data for more refined filtering.  

    Thanks again!

    Steve

  • Any way to get it to dump more than two words of the message portion? How about dumping the entire contents to text!

  • Yes Vam it is possible. I wrote a Pshell script that emails me the entire contents of any error/warning in the Application/System logs along with failed logon attempts from the security log. It creates one text file for each server when the error/warnings/audit failures. I just used the Where-Object {$_.EntryType -eq "Warning" -or $_.EntryType -eq "Error"} logic for Get-EventLog