Learn how to write events with structured EventData.
Introduction
I’ve spent quite some time researching how to create events using EventData with named Data elements. It’s not easy and
is even less easier to write some PowerShell to make it “dynamic”.
EventData with Named Data
In order to enable named Data elements in your event logs, you have to go through several hoops. I won’t go through them
in this post, but here are some links to various posts that can help you get started. It’s not for the faint of heart!
To get the Message Compiler (mc) and Resource Compiler (rc), you will need to download the
Windows 10 SDK and install the Windows SDK for UWP Managed Apps (which required the Signing Tools
for Desktop Apps). To get the ManifestGenerator (EcGenMan), you will need to hit up the the Windows SDK archive section
and download an older version.
EventData without Named Data
Besides super-fast XML filtering, which cannot use wildcards, I’m not entirely sure what the benefit of having named
Data elements would be for general use.
This got me thinking, why not pass EventData in a manner that allows you to easily parse and even search with XML?
Planning
You obviously want to stash some event data into an event in some event log. You should consider creating an EventData
schema for each of your use cases.
Don’t forget to document and share them with your team!
Something like the following
Name
Description
ScriptName
The name of the PowerShell script.
Status
The results of the execution of the PowerShell script.
LogFile
This is were the detailed log can be found.
Also, be sure to establish the event ID ranges that you want to use for each schema.
Event ID Range
Purpose
100-199
Initialization
200-299
Script actions
300-399
Completion
This is a very simple schema. But with it, you would be able to search the logs with an XML filter for warning events
for your event source where the script MyScript.ps1 generated the event.
Once you import the module, you can use the two functions to create a new Windows event log provider and write events
with structured Data, though not named Data elements.
In an elevated PowerShell session, import the module.
{"ScriptName":"MyScript.ps1","Status":"Something didn\u0027t go exactly right.","LogFile":"C:\\ProgramData\\MyLogs\\20191207_MyScript.log"}
IMPORTANT
This contains Unicode escape characters for the single quote (’).
XML View:
1
2
3
4
5
6
- <EventData><Data>{ "ScriptName": "MyScript.ps1", "Status": "Something didn\u0027t go exactly right.", "LogFile": "C:\\ProgramData\\MyLogs\\20191207_MyScript.log" }</Data><Data>ScriptName:MyScript.ps1</Data><Data>Status:Something didn't go exactly right.</Data><Data>LogFile:C:\ProgramData\MyLogs\20191207_MyScript.log</Data></EventData>
MessageFormat: CSV
Event message:
1
2
3
4
"Key","Value"
"ScriptName","MyScript.ps1"
"Status","Something didn't go exactly right."
"LogFile","C:\ProgramData\MyLogs\20191207_MyScript.log"
XML View:
1
2
3
4
5
6
- <EventData><Data>"Key","Value" "ScriptName","MyScript.ps1" "Status","Something didn't go exactly right." "LogFile","C:\ProgramData\MyLogs\20191207_MyScript.log"</Data><Data>ScriptName:MyScript.ps1</Data><Data>Status:Something didn't go exactly right.</Data><Data>LogFile:C:\ProgramData\MyLogs\20191207_MyScript.log</Data></EventData>
MessageFormat: XML
Event message:
1
<?xml version="1.0" encoding="utf-8"?><Objects><ObjectType="System.Collections.Specialized.OrderedDictionary"><PropertyName="Key"Type="System.String">ScriptName</Property><PropertyName="Value"Type="System.String">MyScript.ps1</Property><PropertyName="Key"Type="System.String">Status</Property><PropertyName="Value"Type="System.String">Something didn't go exactly right.</Property><PropertyName="Key"Type="System.String">LogFile</Property><PropertyName="Value"Type="System.String">C:\ProgramData\MyLogs\20191207_MyScript.log</Property></Object></Objects>
XML View
1
2
3
4
5
6
- <EventData><Data><?xml version="1.0" encoding="utf-8"?><Objects><ObjectType="System.Collections.Specialized.OrderedDictionary"><PropertyName="Key"Type="System.String">ScriptName</Property><PropertyName="Value"Type="System.String">MyScript.ps1</Property><PropertyName="Key"Type="System.String">Status</Property><PropertyName="Value"Type="System.String">Something didn't go exactly right.</Property><PropertyName="Key"Type="System.String">LogFile</Property><PropertyName="Value"Type="System.String">C:\ProgramData\MyLogs\20191207_MyScript.log</Property></Object></Objects></Data><Data>ScriptName:MyScript.ps1</Data><Data>Status:Something didn't go exactly right.</Data><Data>LogFile:C:\ProgramData\MyLogs\20191207_MyScript.log</Data></EventData>
Summary
Unless you want to spend a ton of time crafting a manifest and compiling all the pieces into a usable Windows custom
event provider, writing EventData using a structured format such as JSON or XML virtually negates the hassle, while
still providing you the option for querying with a good XML filter.
I hope you’ve found this interesting or informative.
If you have any comments or questions, please post them below.
Thanks for reading! Good luck wrangling your EventData!
TIP
Once things settle down with my new job and life stuff, I will incorporate these two functions into my
PoShEvents module.
If you have been paying attention to its repo, there are a couple new functions to generate XML filters on the fly.