Instantly share code, notes, and snippets.

Embed
What would you like to do?
Expand-WinEvent
function Expand-WinEvent {
<#
.SYNOPSIS
Configured EventLogRecords into EventLogExpandedRecords that are easier to parse
.DESCRIPTION
Convert eventRecords into a more parseable object format, including custom event properties
By expanding the Event XML data into individual properties, this makes WinEvents easier to work with and parse
.NOTES
Inspired by http://blogs.technet.com/b/ashleymcglone/archive/2013/08/28/powershell-get-winevent-xml-madness-getting-details-from-event-logs.aspx
.EXAMPLE
PS C:\> Get-Winevent -LogName Application | Expand-WinEvent
Takes all application logs and expands their properties.
#>
param (
#Specifies an event generated by Get-WinEvent. WARNING: DOES NOT WORK WITH GET-EVENTLOG
[Parameter(Mandatory,ValueFromPipeline)]
[System.Diagnostics.Eventing.Reader.EventLogRecord]$EventLogRecord,
#If specified, outputs a hashtable of object properties rather than the object itself. Useful for creating a subtype.
[Switch]$OutHashTable
)
begin {
#Define the event type and default display properties
$CustomEventRecordType = "System.Diagnostics.Eventing.Reader.EventLogRecordExpanded"
Update-TypeData -TypeName $CustomEventRecordType -DefaultDisplayPropertySet TimeCreated,ID,ProviderName,TaskDisplayName -Force
} #Begin
process {
$EventLogRecord | foreach {
$EventProperties = [ordered]@{
TimeCreated = $PSItem.TimeCreated
ID = $PSItem.ID
LevelDisplayName = $PSItem.LevelDisplayName
ProviderName = $PSItem.ProviderName
TaskDisplayName = if ($PSItem.TaskDisplayName) {$PSItem.TaskDisplayName} else {$null}
MachineName = $PSItem.MachineName
Message = $PSItem.Message
RawEvent = $PSItem
}
#Add all the attribute properties of the event object. This is dynamic and works for all events.
$i = 1
([xml]$PSItem.toxml()).Event.EventData.Data | foreach {
#Skip in the event this is a classic log with no attribute properties
if ($PSItem) {
#If the data is unstructured, just create as "Property1","Property2", etc.
if ($PSItem -isnot [System.XML.XMLElement]){
$PropertyName = "Property" + $i
$EventProperties.Add($PropertyName,$PSItem)
$i++
}
else {
if ($EventProperties.Contains($PSItem.Name)) {
$PropertyName = "property" + $PSItem.Name
} else { $PropertyName = $PSItem.Name }
$EventProperties.Add($PropertyName,$PSItem."#text")
}
} #If ($PSItem)
} #ForEach
if ($OutHashTable) {
$EventProperties
}
else {
$result = [PSCustomObject]$EventProperties
#Assign custom type so it shows properly in Get-Member
$result.PSTypeNames.Insert(0,$customEventRecordType)
$result
}
} #ForEach
} #Process
} #Expand-WinEvent
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment