runtime: FormatDescription() on an EventRecord does not work if properties are passed in explicitly
From user feedback at https://developercommunity.visualstudio.com/content/problem/385483/eventrecordformatdescriptionienumberable.html
I verified this same issue exists in the code being ported to .NET Core here https://github.com/dotnet/corefx/pull/33662
===========start report TLDR: The EventRecord.FormatDescription(IEnumerable<object> values) in the System.Diagnostics.Eventing namespace is not properly inserting the provided values, and is instead returning as if empty strings were supplied.
All testing has been performed on Windows 10, build 17134.345, with .NET Framework 4.7.2. The project I’m using for testing/reproduction has been tested targeting .NET 4.0, .NET 4.5, .NET 4.5.2, .NET 4.6.2, and .NET 4.7.1, and all display the issue.
When calling EventRecord.FormatDescription() with no parameters, the event returns properly formatted, with an example shown below:
“Application ‘C:\Program Files\Microsoft Office\root\Office16\ONENOTEM.EXE’ (pid 14832) cannot be restarted - Application SID does not match Conductor SID…”
However, there is an overload available, EventRecord.FormatDescription(IEnumerable<object> values), the function returns a string that essentially appears as if all the supplied values were empty. Here’s an example of the same event above called with the overload using all of the same property values (meaning the output should be identical):
“Application ‘’ (pid 0) cannot be restarted - .”
I’ve tried both passing the event properties collection in directly, as well as preparing the parameters as a List<object> that is then cast to an IEnumerable<object> prior to passing it in in hopes of removing any odd conversion issues.
I’ve stepped through the reference source, and the .NET framework isn’t really doing any heavy lifting here, it’s basically just a passthrough layer to the underlying WinEvt API, ultimately calling the function described here - https://docs.microsoft.com/en-us/windows/desktop/api/winevt/nf-winevt-evtformatmessage
This leads me to believe one of two things is the case:
Option 1: The .NET Framework is misusing the WinEvt API, perhaps failing to supply a proper value for one of the inputs or flags, and thus getting an odd result. I’m really hoping this is the answer, as I think it would be the easiest to resolve.
Option 2: The underlying WinEvt API is not working as expected even with a proper call. I have no idea how to even begin debugging (or even reporting) an error at this layer, but I’m assuming the MS folks have the tools and connections to follow up on this.
This seems to potentially have been reported as far back as 2007 (https://qa.social.msdn.microsoft.com/Forums/vstudio/en-US/7e0f9fd5-c421-4e13-ac02-211e51189305/how-to-use-eventrecordformatdescriptionienumerableobject?forum=netfxbcl), and I’m also seeing a recent StackOverflow issue that seems to be the same (https://stackoverflow.com/questions/53328834/cannot-get-eventrecord-formatdescriptionienumerableobject-to-work)
I’ve posted basic reproduction code to a GitHub repo, available here: https://github.com/OperatorOverload/WinEventErrorRepro
EventLogQuery eventsQuery = new EventLogQuery("Application",
PathType.LogName, queryString);
EventLogReader = new EventLogReader("*[System/Level=3]");
for (EventRecord eventInstance = logReader.ReadEvent();
eventInstance != null; eventInstance = logReader.ReadEvent())
{
List<object> varRepSet = new List<object>();
for (int i = 0; i < eventInstance.Properties.Count; i++)
{
varRepSet.Add((object)(eventInstance.Properties[i].Value.ToString()));
}
//WORKS
string description1 = eventInstance.FormatDescription();
//BROKEN: format description with the built-in properties array
string description2 = eventInstance.FormatDescription(eventInstance.Properties);
About this issue
- Original URL
- State: open
- Created 6 years ago
- Reactions: 2
- Comments: 23 (9 by maintainers)
@danmoseley Sure, will review the latest contributing info and give it a go.
I imagine it should be as simple as adjusting this code (and any other place that creates a new variant of type String or AnsiString) to set the count:
The Count needs to be whatever wcslen(values[i]) would return in C - no embedded nulls, string is nul-terminated but the nul-terminator is not included in the size. The string still needs to be marshalled as a C-string, not a counted string; the count is just there for fun it seems.
Unfortunately, while the code strongly expects the count to be set for strings that are passed in, it is not (currently) diligent about setting the count for strings that it returns from the various APIs (e.g. EvtGetEventInfo). It’s a bit hypocritical, I know, but without a time machine all I can do it fix it for the next release and hope it doesn’t break app-compat somehow. Everything you get from EvtRender(…, EvtRenderEventValues, …), however, should be suitable for passing back to EvtFormatMessage as long as it isn’t mangled by the marshalling process.
In general, the Count field needs to be set for: