Have you ever tried to use the Windows Event Log GUI?

It’s not a good experience. If you change the log you’re looking at, you are reset to the top of the event history. The filter mechanism is clunky. The buttons are tiny. You have to use the scroll bar when you have many events, guessing and checking where in the history of events each of the tinest movements with the mouse will land you.

Then add the fact you are probably responding to an active issue if you’re using this monstrosity.

But, there is a better way! And if you’ve read my tech notes before, you probably know where this is going.

You can query the event log using the PowerShell commandlet Get-WmiObject. Chain that together with Ansible and some json compression (skipping the first line of output with tail since that’s not json)…

tail -n +2 <(ansible all -i 'host1.fun.corp,' -m win_shell -a "Get-WmiObject -Query \"SELECT * FROM Win32_NTLogEvent WHERE Logfile='System' AND TimeGenerated > '20250128' AND TimeGenerated < '20250129' AND Type='Error'\" | ConvertTo-Json -Compress" --extra-vars "ansible_user=jharding@fun ansible_password=$PASS ansible_connection=winrm ansible_port=5985 ansible_winrm_realm=fun.corp.net ansible_winrm_transport=ntlm") > system.json

And voila! You’ve got your Windows Events exported as a nice json file that you can query on the commandline like a gentleman with jq, and you didn’t even have to RDP to the box!

There is one gotcha you may hit though if you plan to reformat the event timestamps with the Linux date utility. Here’s how Windows Event objects format their timestamps: 20250128233007.502943-000. And here’s what the Linux date utility thinks of this string:

$ date -d "20250128233007.502943-000"
date: invalid date ‘20250128233007.502943-000’

And as there seems to be no way to give date a hint about your time string’s format (you can customize the output though) I cobbled together this little hack to parse the date time nicely:

jq -r '.[]|[.TimeGenerated, .Message] | @tsv' $1 |
  while IFS=$'\t' read -r time message; do
    echo "`echo $time | sed -E 's/^.{8}/& /g' | sed -E 's/^.{11}/&:/g' | sed -E 's/^.{14}/&:/g' | xargs -0 date -d`   $message"
  done

Essentially we’re coercing the Windows Event timestamps from 20250128233007.502943-000 into 20250128 23:30:07.502943-000 using sed, which date will accept:

$ date -d "20250128 23:30:07.502943-000"
Tue Jan 28 23:30:07 UTC 2025

Now your Windows Events can be printed out like this:

Tue Jan 28 23:30:07 UTC 2025   The MyInternalApp service terminated with the following service-specific error: \r\nThe system cannot find the path specified.