0

I need to read specific informatiosn from eventlog. For example - Security log, ID 4648. With simple "Get-Eventlog" i can't get informations like TargetUserName or TargetDomainName in easy way - only from .message value, but it's way harder to read one/two informations from full text. Can i read this from XML eventlog, without exporting log to file?

XML eventlog

0

3 Answers 3

4

Using the Get-WinEvent cmdlet, you can grab the XML Event data and create your output from there.

Below code does exactly that and returns an array of PsCustomObjects with all event properties found.

$result = Get-WinEvent -FilterHashtable @{LogName="Security";Id=4648} -MaxEvents 100 | ForEach-Object {
    # convert the event to XML and grab the Event node
    $eventXml = ([xml]$_.ToXml()).Event
    # create an ordered hashtable object to collect all data
    # add some information from the xml 'System' node first
    $evt = [ordered]@{
        EventDate = [DateTime]$eventXml.System.TimeCreated.SystemTime
        Computer  = $eventXml.System.Computer
    }
    $eventXml.EventData.ChildNodes | ForEach-Object { $evt[$_.Name] = $_.'#text' }
    # output as PsCustomObject. This ensures the $result array can be written to CSV easily
    [PsCustomObject]$evt
}

# output to screen
$result

# output to CSV file
$result | Export-Csv D:\test.csv -NoTypeInformation
Sign up to request clarification or add additional context in comments.

1 Comment

You can filter on named data too, more so in powershell 7.
1

I would recommend using as described here: https://devblogs.microsoft.com/scripting/data-mine-the-windows-event-log-by-using-powershell-and-xml/

and here: https://blogs.technet.microsoft.com/ashleymcglone/2013/08/28/powershell-get-winevent-xml-madness-getting-details-from-event-logs/

Which go into detail to achieve what you're looking for, additionally you can look further into the Get-EventLog cmdtlet: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-eventlog?view=powershell-5.1

Comments

-1

I was looking to do something similar after Windows 11 update KB5063878 made Diablo3 unstable. I couldn't get Theo's code to get the AppName from this kind of XML, so rolled my own code.

<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
  <System>
    ....
  </System>
  <EventData>
    <Data Name="AppName">SnippingTool.exe</Data>
    ...    
  </EventData>
</Event>

I identified 4 programs ($targetApps) that consistently failed with Event Id 1000, and then added any Application informational events in the preceding 5 seconds to see if there was any correlation:

Feel free to adapt this code to your requirements:

param (
    [int]$SecondsBack = 5,
    [string[]]$TargetApps = @(
        "Diablo III64.exe",
        "Battle.net.exe",
        "Copilot.exe",
        "SnippingTool.exe"
    )
)
$desktopPath = "$env:SystemDrive\Users\$env:USERNAME\Desktop"
$csvPath = Join-Path $desktopPath "CrashEvents_Last7Days.csv"
$logName = "Application"
$eventID = 1000
$parsedEvents = @()

# Define time window
$now = Get-Date
$startTime = $now.AddDays(-7)

# Fetch Event ID 1000 entries from the last 7 days
$rawEvents = Get-WinEvent -FilterHashtable @{
    LogName   = $logName
    Id        = $eventID
    StartTime = $startTime
    EndTime   = $now
}
Write-Host "rawEvents count: $($rawEvents.Count)"
foreach ($event in $rawEvents) {
    $eventXml = [xml]$event.ToXml()
    $dataFields = @{}
    
    foreach ($data in $eventXml.Event.EventData.Data) {
        if ($data.Name) {
            $dataFields[$data.Name] = $data.'#text'
        }
    }
    $appName = $dataFields["AppName"]
    if ($TargetApps -contains $appName) {
        $eventMsg = ($event.Message -split "`r?`n")[0].Trim()
        $anchorTime = $event.TimeCreated
        $parsedEvents += [PSCustomObject]@{
            TimeCreated     = $anchorTime
            Message         = $eventMsg
            EventID         = $event.Id
            EntryType       = $event.EntryType
            RecType         = "anchor"
            AppName         = $appName
            ExceptionCode   = $dataFields["ExceptionCode"]
            FaultOffset     = $dataFields["FaultOffset"]
            AppPath         = $dataFields["AppPath"]
            ReportID        = $dataFields["ReportId"]
        }
        # Define context window
        $windowStart = $anchorTime.AddSeconds(-$SecondsBack)
        $windowEnd   = $anchorTime.AddMilliseconds(-1)
        # Get preceding events
        $contextEvents = Get-WinEvent -FilterHashtable @{
            LogName   = $logName
            StartTime = $windowStart
            EndTime   = $windowEnd
        }  -ErrorAction SilentlyContinue
        foreach ($ctx in $contextEvents) {
            $ctxMsg = ($ctx.Message -split "`r?`n")[0].Trim()
            $parsedEvents += [PSCustomObject]@{
                TimeCreated   = $ctx.TimeCreated
                Message       = $ctxMsg
                EventID       = $ctx.Id
                EntryType     = $event.EntryType
                RecType       = "Context"
                AppName       = [string]::Empty
                ExceptionCode = [string]::Empty
                FaultOffset   = [string]::Empty
                AppPath       = [string]::Empty
                ReportID      = [string]::Empty
            }
        }
    }
}

if ($parsedEvents.Count -gt 0) {
    $parsedEvents | Sort-Object TimeCreated  -Descending | Export-Csv -Path $csvPath -NoTypeInformation -Encoding UTF8
    Write-Host "✅ Exported $($parsedEvents.Count) rows of events to CSV : $csvPath"
} else {
    Write-Host "No matching crash events found for target apps."
}

If you go to the EventLog and right click any errors with the event_id 1000. you can choose copy, then copy details as text to see the weird Text with XML appended to the end.. It's more like a key/value pair - with a colon between. But all the XML is at the end. Bing was able to help in getting the syntax of just looking for the four apps that seemed to be giving me issues. The dot notation is similar to xpath or Groovy. Embedded properties depending on node depth. At the end, it sorts the CSV by timestamp descending, so latest are at the beginning of the CSV.


The -ErrorAction SilentlyContinue line stops script from throwing an exception if the filter for the preceding 5 seconds yields no results.


You can also invoke the ps1 file and override the SecondsBack argument when you call code.

For example

powershell .\scriptname.ps1 -SecondsBack 3


There are certain exception codes Co-Pilot helped me classify you may find useful too:

c0000409 : stack buffer overrun = stack corruption often points to unsafe buffer handling or a failed guard.

c000027b: Invalid Window Handle - usually tied to shell extensions, window focus issues, or corrupted UI state.

c0000005: Access Violation - That’s classic for null dereference, bad pointer access, or corrupted memory.


Co-Pilot's synopsis of what Changed with KB5063878:

This update appears to have tightened enforcement:

• Stricter Code Integrity Enforcement: Modules with unresolved symbols or unsigned binaries may now fail outright instead of being sandboxed.

• Reduced Tolerance for Buffer Overruns: Exception (stack buffer overrun) is no longer soft-failed—it’s logged and crashes the app.

• Secure Boot Policy Hardening: If Diablo III wasn’t properly registered with SecureBootCertificates, it may now fail to launch or crash mid-session. In short: Microsoft clamped down on silent recovery, and now you’re seeing the true fault surface.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.