runtime: System.Diagnostics.Eventing.Reader.EventLogRecord throws an InvalidOperationException on Windows 11

Description

On Windows 11, System.Diagnostics.Eventing.Reader.EventLogRecord (version 5.0.1) throws an InvalidOperationException when accessing its Properties:

System.InvalidOperationException: We do not have 18 variants given for the UnsafeNativeMethods.EvtRenderFlags.EvtRenderEventValues flag. (System Properties)

This happens for any event log file and I can reproduce with a very minimal sample program (see [Reproduction Steps]). The issue does not occur when using the same log file on Win10.

The exception occurs on the following call stack:

at System.Diagnostics.Eventing.Reader.NativeWrapper.EvtRenderBufferWithContextSystem(EventLogHandle contextHandle, EventLogHandle eventHandle, EvtRenderFlags flag, SystemProperties systemProperties, Int32 SYSTEM_PROPERTY_COUNT)
at System.Diagnostics.Eventing.Reader.EventLogRecord.PrepareSystemData()
at System.Diagnostics.Eventing.Reader.EventLogRecord.get_Id()
at WinEvent.Program.Main(String[] args) 

The problem is that SYSTEM_PROPERTY_COUNT is hard coded to 18, but propCount is 16 on Win11. See below:

https://github.com/dotnet/runtime/blob/895c99cc502913fd7393b95af7cae5b9e6fbdea3/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/NativeWrapper.cs

      public static void EvtRenderBufferWithContextSystem(EventLogHandle contextHandle, EventLogHandle eventHandle, UnsafeNativeMethods.EvtRenderFlags flag, SystemProperties systemProperties, int SYSTEM_PROPERTY_COUNT)
      {
          IntPtr buffer = IntPtr.Zero;
          IntPtr pointer = IntPtr.Zero;
          int bufferNeeded;
          int propCount;

          try
          {
              bool status = UnsafeNativeMethods.EvtRender(contextHandle, eventHandle, flag, 0, IntPtr.Zero, out bufferNeeded, out propCount);
              if (!status)
              {
                  int error = Marshal.GetLastWin32Error();
                  if (error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
                      EventLogException.Throw(error);
              }

              buffer = Marshal.AllocHGlobal((int)bufferNeeded);
              status = UnsafeNativeMethods.EvtRender(contextHandle, eventHandle, flag, bufferNeeded, buffer, out bufferNeeded, out propCount);
              int win32Error = Marshal.GetLastWin32Error();
              if (!status)
                  EventLogException.Throw(win32Error);

              if (propCount != SYSTEM_PROPERTY_COUNT)  // <<-- Here propCount is 16 in Win11
                  throw new InvalidOperationException("We do not have " + SYSTEM_PROPERTY_COUNT + " variants given for the UnsafeNativeMethods.EvtRenderFlags.EvtRenderEventValues flag. (System Properties)");

https://github.com/dotnet/runtime/blob/57bfe474518ab5b7cfe6bf7424a79ce3af9d6657/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/EventLogRecord.cs

namespace System.Diagnostics.Eventing.Reader
{
    public class EventLogRecord : EventRecord
    {
        private const int SYSTEM_PROPERTY_COUNT = 18;  <<-- 

I’m not sure if this is considered as a Win11’s bug. According to EvtRender, I don’t see any guarantee about PropertyCount.

Note that PowerShell Get-WinEvent is also affected by this because it uses System.Diagnostics.Eventing.Reader.EventLogRecord:

Get-WinEvent : We do not have 18 variants given for the  UnsafeNativeMethods.EvtRenderFlags.EvtRenderEventValues flag. (System Properties)
At line:1 char:1
+ Get-WinEvent -Path "C:\Users\...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Get-WinEvent], InvalidOperationException
    + FullyQualifiedErrorId : We do not have 18 variants given for the  UnsafeNativeMethods.EvtRenderFlags.EvtRenderEventValues flag. (System Properties),Microsoft.PowerShell.Commands.GetWinEventCommand

__

Reproduction Steps

I can reproduce with the following simple program:

using System;
using System.Diagnostics.Eventing.Reader;

class Program
{
    static void Main(string[] args)
    {
        var file = args[0];
        var query = new EventLogQuery(file, PathType.FilePath, "*");

        using (var reader = new EventLogReader(query))
        {
            EventRecord record;
            while ((record = reader.ReadEvent()) != null)
            {
                Console.WriteLine($"event {record.Id}");
            }
        }
    }
}

Or, as I mentioned, you can see the repro with PowerShell’s Get-WinEvent too.

Expected behavior

EventLogRecord shouldn’t fail with InvalidOperationException even if it’s run on Win11.

Actual behavior

On Windows 11, System.Diagnostics.Eventing.Reader.EventLogRecord (version 5.0.1) throws an InvalidOperationException when accessing its Properties.

Regression?

No response

Known Workarounds

No response

Configuration

I’ve tested with .NET Core (5.0), .NET Framework.

Other information

No response

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 38 (13 by maintainers)

Most upvoted comments

While I still can’t repro the issue, I did just discover the bug hiding out in the Windows Server 2022 code (the perils of refactoring some massive files into smaller pieces between WS2022 and Win11…). I’ll see that it gets fixed there too, and perhaps try to understand why I can’t reproduce the issue at all on WS2022 even with the buggy code in hand.

This issue exists in Server 2022 as well. Is the fix being ported to there as well?

Looks to me like it also impacts .NETFramework: https://referencesource.microsoft.com/#System.Core/System/Diagnostics/Eventing/Reader/EventLogRecord.cs,28

Yes we should fix this. First step is fix in main then we can find all the places to backport.

This is both a .net bug and a Windows bug.

The Windows API says the number of properties will match the number of items in the system properties enum. It does not say there will be 18 items forever, only that there will be at least 18 items. .Net’s insistence on checking for exactly 18 items is blocking us from adding new properties as we evolve Windows. The code needs to be updated to verify that it received at least as many items in the array as it knows about, and ignore any additional items; in practice this will mean at least 18 but more is OK.

There is currently a bug in Windows 11 where it may return a number less than 18 if the last few items in the array are empty. This is being fixed and will go out on Windows Update in a future update.

Simply put. If this .NET 4.8 call doesn’t work on Windows Server 2022 the way it works on every other version of Windows Server then we are unable to support our product on Windows Server 2022 and have to recommend that customers don’t upgrade beyond Windows Server 2019. Microsoft customer quite honestly don’t care if it is a Windows or .NET bug, it’s just a Microsoft issue. It used to work fine for years and then somebody broke it. Pls get it sorted.

The Windows fix is available in the latest Windows Insider builds, and will be available through Windows Update soon.

Yes

On Thu, 28 Oct 2021 at 10:42, Dan Moseley @.***> wrote:

We still need to fix a above

Net’s insistence on checking for exactly 18 items is blocking us from adding new properties as we evolve Windows.

Any interest in offering a PR?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/dotnet/runtime/issues/60740#issuecomment-953508372, or unsubscribe https://github.com/notifications/unsubscribe-auth/ARPSOYQPAD3HRGANEQMA3QLUJDLUVANCNFSM5GPDEJPA . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

– Karan Aggarwal