C# System.AccessViolationException at Microsoft.Win32.UnsafeNativeMethods.EvtClose(IntPtr) while querying

0

I have a Windows Service which has a thread that polls particular Windows Event logs every 5 minutes, looking for events that match a particular EventID.

  • This service is running on Win10 1607 Enterprise LTSB systems, with .NET Framework 4.0.30319.42000 (4.6.1).

  • Here's a snippet for querying the Windows Firewall event log:

try
{
    // ******************************
    // Windows Firewall Events.
    // ******************************

    // Event log query
    var firewallQuery = new EventLogQuery("Microsoft-Windows-Windows Firewall With Advanced Security/Firewall", PathType.LogName, "*[System[EventID=2004 or EventID=2005 or EventID=2006]]");
    var firewallReader = new EventLogReader(firewallQuery);
    EventRecord firewallEntry;

    // Iterate the event search results
    while ((firewallEntry = firewallReader.ReadEvent()) != null)
    {
        // Did the event occur >current baseline?
        if (firewallEntry.TimeCreated.HasValue && 
            firewallEntry.TimeCreated.Value.CompareTo(BaselineTimestamp) > 0)
        {
            try
            {
                // Select the relavent properties
                EventLogPropertySelector fwEventPropSelector = new EventLogPropertySelector(new[] {
                    "Event/EventData/Data[@Name='RuleName']",
                    "Event/EventData/Data[@Name='Profiles']",
                    "Event/EventData/Data[@Name='Direction']",
                    "Event/EventData/Data[@Name='Action']",
                    "Event/EventData/Data[@Name='ApplicationPath']",
                    "Event/EventData/Data[@Name='ServiceName']",
                    "Event/EventData/Data[@Name='Protocol']",
                    "Event/EventData/Data[@Name='LocalPorts']",
                    "Event/EventData/Data[@Name='RemotePorts']",
                    "Event/EventData/Data[@Name='ModifyingUser']",
                    "Event/EventData/Data[@Name='ModifyingApplication']"});

                // Retrieve enumeration of selected values
                IList<object> fwEventPropValues = ((EventLogRecord)firewallEntry).GetPropertyValues(fwEventPropSelector);

                // Free resource.
                fwEventPropSelector.Dispose();

                // Object to store any new event
                WindowsEvent curEvent = null;

                // Which event?
                switch (firewallEntry.Id)
                {
                    case 2004:
                                            
                        // Firewall rule added
                        curEvent = new WindowsEvent("Windows Firewall",
                            firewallEntry.TimeCreated.Value.ToString(),
                            firewallEntry.Id,
                            "Firewall - Add Rule",
                            "Rule=" + fwEventPropValues[0].ToString() + ";" +
                            "Profile=" + fwProfile.FirstOrDefault(v => v.Item1 == fwEventPropValues[1].ToString()).Item2 + ";" +
                            "Direction=" + fwDirection.FirstOrDefault(v => v.Item1 == fwEventPropValues[2].ToString()).Item2 + ";" +
                            "Action=" + fwAction.FirstOrDefault(v => v.Item1 == fwEventPropValues[3].ToString()).Item2 + ";" +
                            "App=" + fwEventPropValues[4].ToString() + ";" +
                            "Service=" + fwEventPropValues[5].ToString() + ";" +
                            "Protocol=" + fwProtocol.FirstOrDefault(v => v.Item1 == fwEventPropValues[6].ToString()).Item2 + ";" +
                            "LocalPort=" + fwEventPropValues[7].ToString() + ";" +
                            "RemotePort=" + fwEventPropValues[8].ToString() + ";" +
                            "ModifyUser=" + new System.Security.Principal.SecurityIdentifier(
                                                    fwEventPropValues[9].ToString()).Translate(typeof(System.Security.Principal.NTAccount)).ToString() + ";" +
                            "ModifyApp=" + fwEventPropValues[10].ToString() + ";");

                        break;

                    case 2005:
                                            
                        // Firewall rule changed
                        curEvent = new WindowsEvent("Windows Firewall",
                            firewallEntry.TimeCreated.Value.ToString(),
                            firewallEntry.Id,
                            "Firewall - Changed Rule",
                            "Rule=" + fwEventPropValues[0].ToString() + ";" +
                            "Profile=" + fwProfile.FirstOrDefault(v => v.Item1 == fwEventPropValues[1].ToString()).Item2 + ";" +
                            "Direction=" + fwDirection.FirstOrDefault(v => v.Item1 == fwEventPropValues[2].ToString()).Item2 + ";" +
                            "Action=" + fwAction.FirstOrDefault(v => v.Item1 == fwEventPropValues[3].ToString()).Item2 + ";" +
                            "App=" + fwEventPropValues[4].ToString() + ";" +
                            "Service=" + fwEventPropValues[5].ToString() + ";" +
                            "Protocol=" + fwProtocol.FirstOrDefault(v => v.Item1 == fwEventPropValues[6].ToString()).Item2 + ";" +
                            "LocalPort=" + fwEventPropValues[7].ToString() + ";" +
                            "RemotePort=" + fwEventPropValues[8].ToString() + ";" +
                            "ModifyUser=" + new System.Security.Principal.SecurityIdentifier(
                                                    fwEventPropValues[9].ToString()).Translate(typeof(System.Security.Principal.NTAccount)).ToString() + ";" +
                            "ModifyApp=" + fwEventPropValues[10].ToString() + ";");

                        break;

                    case 2006:
                                            
                        // Firewall rule deleted
                        curEvent = new WindowsEvent("Windows Firewall",
                            firewallEntry.TimeCreated.Value.ToString(),
                            firewallEntry.Id,
                            "Firewall - Deleted Rule",
                            "Rule=" + fwEventPropValues[0].ToString() + ";" +
                            "ModifyUser=" + new System.Security.Principal.SecurityIdentifier(
                                                    fwEventPropValues[9].ToString()).Translate(typeof(System.Security.Principal.NTAccount)).ToString() + ";" +
                            "ModifyApp=" + fwEventPropValues[10].ToString() + ";");

                        break;

                    default:

                        // Not an event we planned for
                        Logger.WriteDebug(callStack, "Unrecognized event code:" + firewallEntry.Id.ToString(), true);

                        break;
                }

                // Did we capture an event?
                if (curEvent != null)
                {
                    // Set flag
                    bool uniqueEvent = true;

                    // Iterate all recorded events
                    foreach (WindowsEvent we in WindowsEvent.EventList)
                    {
                        // Does the event match an existing event?
                        if (we.Equals(curEvent))
                        {
                            // Unset flag
                            uniqueEvent = false;

                            break;
                        }
                    }

                    // Is this a unique event?
                    if (uniqueEvent)
                    {
                        // Set flag
                        unreportedWindowsEvent = true;

                        // Add to list
                        WindowsEvent.EventList.Add(curEvent);
                    }
                }
            }
            catch (Exception e)
            {
                Logger.WriteException(callStack, e, "Failed to process record [" + firewallEntry.FormatDescription().Replace(Environment.NewLine, " | ") + "]");
            }
        }
    }

    // Dispose resources.
    firewallReader.Dispose();
}
catch (Exception e)
{
    Logger.WriteException(callStack, e, "Unable to read security events.");
}
  • There are about (4) other similar blocks of code, polling from the Defender, Security and System event logs, each for particular EventIDs. Each snippet has it's own try/catch, wrapped in an outer try/catch.

  • The EventLogReader object implemented IDisposed, so it's disposed at the end of each operation.

THE PROBLEM: Approximately once or twice a month, the entire thread/Windows Service will crash with:

Application: MyService.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.AccessViolationException
   at Microsoft.Win32.UnsafeNativeMethods.EvtClose(IntPtr)
   at System.Diagnostics.Eventing.Reader.EventLogHandle.ReleaseHandle()
   at System.Runtime.InteropServices.SafeHandle.InternalFinalize()
   at System.Runtime.InteropServices.SafeHandle.Finalize()
Faulting application name: MyService.exe, version: 1.9.7543.25123, time stamp: 0x5f46a286
Faulting module name: wevtapi.dll, version: 10.0.14393.2457, time stamp: 0x5b7e2ba7
Exception code: 0xc0000005
Fault offset: 0x0000000000008636
Faulting process id: 0x99c
Faulting application start time: 0x01d698f934ae131f
Faulting application path: C:\...
Faulting module path: C:\WINDOWS\SYSTEM32\wevtapi.dll
Report Id: 36cded2c-137d-429f-b4cc-4c19b8005dd5
Faulting package full name: 
Faulting package-relative application ID: 

To me, this appears to be a case of Managed code having a crash calling Un-Managed code on the backend. But my BIG QUESTION, is why/how this eludes capture by the try/catch blocks?

c#
exception
event-log
asked on Stack Overflow Oct 5, 2020 by Brian

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0