[System.Diagnostics.Eventing.Reader.EventLogRecord]. PowerShell is being nice and picking just four common properties to show us, but there are more properties that we can access by storing the results to a variable or using a cmdlet like
Format-List, or even
Here are some of the properties you might find useful:
Id – Event ID
Level – Numeric representation of the event level
LevelDisplayName – Event level (Information, Error, Warning, etc.)
LogName – Log name (Application, Security, System, etc.)
MachineName – Name of the computer the event is from
Message – Full message of the event
ProviderName – Name of the provider (source) that wrote the event
You can also dig into the message data attached to the event. Event log messages are defined by the Event ID, so all events with the same Event ID have the same basic message. Messages can also have placeholders that get filled in with specific values for each instance of that Event ID. These fill-in-the-blank values are called “insertion strings,” and they can be very useful.
For example, let’s say I grabbed an event out of the Application log and stored it in a variable
$x. If I just examine
$x, I can see the full message of the event is “The session ‘183c457c-733c-445d-b5d6-f04fc9623c8b’ was disconnected”.
This is where things get interesting. Since Windows Vista, event logs have been stored in XML format. If you run
(Get-WinEvent -ListLog Application).LogFilePath you’ll see the .evtx extension on the file. The
EventLogRecord objects that
Get-WinEvent returns have a
ToXml method that I can use to get to the XML underneath the object; this is where the insertion string data is stored.
By converting the event to XML and looking at the insertion strings, I can get direct access to the value that was inserted into the message without having to parse the full message and extract it. Here is the code to do that:
ToXml method returns a string containing the XML, and putting the
accelerator in front of it tells PowerShell to read that string and create an XML object from it. From there, I navigate the XML hierarchy to the place where the insertion string data is stored.
The messages for different Event IDs can have different numbers of insertion strings, and you may need to explore a little to figure out exactly how to pull the specific piece of data you’re looking for, but all events for a given Event ID will be consistent. The example above uses a simple event on purpose, but one example of how I’ve used this in my automation is when pulling logon events from the Security log. Event 4624, which records a successful logon, contains insertion strings for which user is logging on, what domain they belong to, what kind of authentication they used, and more.
All the cool stuff we just covered above? You can do all of that on remote targets as well. There are two parameters you can use to have Get-WinEvent get values from a remote computer:
ComputerName – Lets you specify which computer to connect to remotely
Credential – Lets you specify a credential to use when connecting, in case your current session is not running under an account with the appropriate permissions.
Get-WinEvent does not use PSRemoting to get remote data; just the Event Log Service. This requires TCP port 135 and a dynamically chosen port above 1024 to be open in the firewall.
Putting It All Together
There is more to discover in using the
Get-WinEvent cmdlet and the data that it returns but, hopefully, this introduction serves as a thorough foundation for accessing the event logs from PowerShell. These techniques for discovering, filtering, and extracting meaning from the event logs can be applied in an interactive PowerShell session or an automated script. They can also be used to read the event logs on your local machine or a remote target. It’s hard to know what data you will be searching for to meet your requirements until you are faced with them, but one thing is for sure: the event logs probably have at least some of the data you need, and now you know how to get it!