File: System\Diagnostics\EventLogTraceListener.cs
Web Access
Project: src\src\runtime\src\libraries\System.Diagnostics.EventLog\src\System.Diagnostics.EventLog.csproj (System.Diagnostics.EventLog)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Text;

namespace System.Diagnostics
{
    public sealed class EventLogTraceListener : TraceListener
    {
        private bool _nameSet;

        public EventLogTraceListener()
        {
        }

        public EventLogTraceListener(EventLog? eventLog)
            : base(eventLog != null ? eventLog.Source : string.Empty)
        {
            EventLog = eventLog;
        }

        public EventLogTraceListener(string source)
        {
            EventLog = new EventLog
            {
                Source = source
            };
        }

        public EventLog? EventLog
        {
            get;
            set;
        }

        [AllowNull]
        public override string Name
        {
            get
            {
                if (!_nameSet && EventLog != null)
                {
                    _nameSet = true;
                    base.Name = EventLog.Source;
                }

                return base.Name;
            }

            set
            {
                _nameSet = true;
                base.Name = value;
            }
        }

        public override void Close() => EventLog?.Close();

        protected override void Dispose(bool disposing)
        {
            try
            {
                Close();
                if (!disposing)
                {
                    EventLog = null;
                }
            }
            finally
            {
                base.Dispose(disposing);
            }
        }

        public override void Write(string? message) => EventLog?.WriteEntry(message);

        public override void WriteLine(string? message) => Write(message);

        [ComVisible(false)]
        public override void TraceEvent(TraceEventCache? eventCache, string source, TraceEventType severity, int id, string? format, params object?[]? args)
        {
            if (Filter != null && !Filter.ShouldTrace(eventCache, source, severity, id, format, args, null, null))
                return;

            EventInstance data = CreateEventInstance(severity, id);

            if (args == null || args.Length == 0)
            {
                EventLog!.WriteEvent(data, format);
            }
            else if (string.IsNullOrEmpty(format))
            {
                string?[] strings = new string[args.Length];
                for (int i = 0; i < args.Length; i++)
                {
                    strings[i] = args[i]?.ToString();
                }

                EventLog!.WriteEvent(data, strings);
            }
            else
            {
                EventLog!.WriteEvent(data, string.Format(CultureInfo.InvariantCulture, format, args));
            }

        }

        [ComVisible(false)]
        public override void TraceEvent(TraceEventCache? eventCache, string source, TraceEventType severity, int id, string? message)
        {
            if (Filter != null && !Filter.ShouldTrace(eventCache, source, severity, id, message, null, null, null))
                return;

            EventLog!.WriteEvent(CreateEventInstance(severity, id), message);
        }

        [ComVisible(false)]
        public override void TraceData(TraceEventCache? eventCache, string source, TraceEventType severity, int id, object? data)
        {
            if (Filter != null && !Filter.ShouldTrace(eventCache, source, severity, id, null, null, data, null))
                return;

            EventLog!.WriteEvent(CreateEventInstance(severity, id), new object?[] { data });
        }

        [ComVisible(false)]
        public override void TraceData(TraceEventCache? eventCache, string source, TraceEventType severity, int id, params object?[]? data)
        {
            if (Filter != null && !Filter.ShouldTrace(eventCache, source, severity, id, null, null, null, data))
                return;

            EventInstance inst = CreateEventInstance(severity, id);

            var sb = new StringBuilder();
            if (data != null)
            {
                for (int i = 0; i < data.Length; i++)
                {
                    if (i != 0)
                        sb.Append(", ");

                    object? datum = data[i];
                    if (datum != null)
                        sb.Append(datum.ToString());
                }
            }

            EventLog!.WriteEvent(inst, new object[] { sb.ToString() });
        }

        private static EventInstance CreateEventInstance(TraceEventType severity, int id)
        {
            // Win32 EventLog has an implicit cap at ushort.MaxValue
            // We need to cap this explicitly to prevent larger value
            // being wrongly casted
            if (id > ushort.MaxValue)
                id = ushort.MaxValue;

            // Ideally we need to pick a value other than '0' as zero is
            // a commonly used EventId by most applications
            if (id < ushort.MinValue)
                id = ushort.MinValue;

            EventInstance data = new EventInstance(id, 0);

            if (severity == TraceEventType.Error || severity == TraceEventType.Critical)
                data.EntryType = EventLogEntryType.Error;
            else if (severity == TraceEventType.Warning)
                data.EntryType = EventLogEntryType.Warning;
            else
                data.EntryType = EventLogEntryType.Information;

            return data;
        }

    }
}