Get EventData from Get-WinEvent from File - How to group by EventData.Data?

434 views Asked by At

An EventLog was exported from a server to a file named Exported_ErrorLog.evtx.

I would like to

  • filter all entries created in 2023
  • group by Text <EventData><Data> (see xml below)
  • and count

I am able to read from file (see Learn Powershell - Get-WinEvent)

Get-WinEvent -Path 'C:\dev\powershell\EventLogs\Exported_ErrorLog.evtx'

But the command help from

Powershell_Get-WinEvent_fromFile

does not really help how i can access the entries underlying properties.

.NET Log Entry

For example one Entry looks like this

<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
  <Provider Name=".NET Runtime" /> 
  <EventID Qualifiers="0">1000</EventID> 
  <Level>2</Level> 
  <Task>0</Task> 
  <Keywords>0x80000000000000</Keywords> 
  <TimeCreated SystemTime="2023-01-16T21:53:35.0432325Z" /> 
  <EventRecordID>7198</EventRecordID> 
  <Channel>Application</Channel> 
  <Computer>our.puny.server.dotcombubble</Computer> 
  <Security /> 
</System>
<EventData>
  <Data>
   Category: Microsoft.EntityFrameworkCore.Database.Command 
   EventId: 20102 
   SpanId: d212092536b29df0 
   TraceId: b6c16c00e29da216e66009bc80c78c2d 
   ParentId: 0000000000000000 
   RequestId: 8000023a-0001-fd00-b63f-84710c7967bb 
   RequestPath: /User/Login 
   ActionId: f65f32b4-7dff-4c5d-8463-4f350cae7583 
   ActionName: /User/Login Failed executing DbCommand (16ms) 
       [Parameters=[@__user_UserId_0= ... FROM [dbo].[myTbl] AS [c] 
                    WHERE [c].[userId] = @__user_UserId_0
  </Data> 
</EventData>
  </Event>

Application Error Log Entry

<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
  <Provider Name="Application Error" /> 
  <EventID Qualifiers="0">1000</EventID> 
  <Level>2</Level> 
  <Task>100</Task> 
  <Keywords>0x80000000000000</Keywords> 
  <TimeCreated SystemTime="2023-01-18T07:59:41.3126855Z" /> 
  <EventRecordID>7461</EventRecordID> 
  <Channel>Application</Channel> 
  <Computer>our.puny.server.dotcombubble</Computer> 
  <Security /> 
</System>
<EventData>
  <Data>w3wp.exe</Data> 
  <Data>10.0.17763.1</Data> 
  <Data>cfdb13d8</Data> 
  <Data>KERNELBASE.dll</Data> 
  <Data>10.0.17763.3650</Data> 
  <Data>62549bf9</Data> 
  <Data>e0434352</Data> 
  <Data>0000000000034859</Data> 
  <Data>530</Data> 
  <Data>01d92b12c51b52c6</Data> 
  <Data>c:\windows\system32\inetsrv\w3wp.exe</Data> 
  <Data>C:\WINDOWS\System32\KERNELBASE.dll</Data> 
  <Data>ef0199e6-4724-4996-ad46-69cf5db0f138</Data> 
  <Data /> 
  <Data /> 
</EventData>
</Event>

Questions

It seems to me that the cmd-let documentation is brief.

  • Provides .Net better documented libraries to read event logs?
  • How can i access the properties <EventData><Data> of each log entry?
  • How to group all entries with the same <EventData><Data>?
  • How can the result from Get-WinEvent -Path ... be piped to another command?

Edit / Update: Attempts

With the help of mikes answers below i wrote this script

$filter = @{     
    ID        = 1000, 1003
    startTime = [datetime]"1/1/2023"
    path      = "C:\dev\powershell\EventLogs\Exported_ErrorLog.evtx"
} 

$Events = Get-WinEvent -FilterHashtable $filter

$CustomEventObjects = foreach ($event in $Events) {
    $xmlevent = [xml]$event.toxml()

    [pscustomobject]@{
        TimeCreated    = $event.TimeCreated
        EventRecordID  = $event.RecordId
        Message        = $event.Message
    }
}
$CustomEventObjects

I assume that $event is related to System.Diagnostics.Eventing.Reader.EventLogRecord and EventRecord

The script above results in this output

EventLog

Two things are unclear

  • Why is the message truncated and how can it be fixed?
  • How to use $xmlevent to acces any properties
1

There are 1 answers

7
mike crowley On

This appears to be a PowerShell question, though you also have a c# tag, so hopefully this is what you're looking for. I also don't have enough SO reputation to comment, so apologies if this answer is premature.

Events have a toxml method which makes this possible:

$event.toxml()

You could continue to work with the XML directly, or convert it to a PS Object, which is what I've done ([xml]$event.toxml()). You can swap out your event data values as appropriate.

$filter = @{     
    ID        = 1000, 1003
    startTime = [datetime]"1/1/2023"
    path      = "C:\tmp\SavedEvents.evtx"
} 
    
$Events = Get-WinEvent -FilterHashtable $filter
    
$CustomEventObjects = foreach ($event in $events) {
    $xmlevent = [xml]$event.toxml()
    
    [pscustomobject]@{
        TimeCreated = $event.TimeCreated
        RequestPath = ($xmlevent.Event.EventData.Data | Where-Object name -eq RequestPath).'#text'
        ActionName  = ($xmlevent.Event.EventData.Data | Where-Object name -eq ActionName).'#text'
        ActionId    = ($xmlevent.Event.EventData.Data | Where-Object name -eq ActionId).'#text'
    }
}

#possible outputs, but you can take it from here:
$CustomEventObjects | Group-Object RequestPath
$CustomEventObjects | Group-Object ActionName
$CustomEventObjects | Group-Object ActionId

EDIT 25Jan2023 - replaced my example attributes with 3 from your actual event.