Index: EventLogAppender.cs =================================================================== --- EventLogAppender.cs (revision 1415628) +++ EventLogAppender.cs (working copy) @@ -454,10 +454,10 @@ { string eventTxt = RenderLoggingEvent(loggingEvent); - // There is a limit of 32K characters for an event log message - if (eventTxt.Length > 32000) + // There is a limit of about 32K characters for an event log message + if (eventTxt.Length > MAX_EVENTLOG_MESSAGE_SIZE) { - eventTxt = eventTxt.Substring(0, 32000); + eventTxt = eventTxt.Substring(0, MAX_EVENTLOG_MESSAGE_SIZE); } EventLogEntryType entryType = GetEntryType(loggingEvent.Level); @@ -614,6 +614,74 @@ /// private readonly static Type declaringType = typeof(EventLogAppender); + /// + /// The maximum size that the operating system supports for + /// a event log message. + /// + /// + /// Used to determine the maximum string length that can be written + /// to the operating system event log and eventually truncate a string + /// that exceeds the limits. + /// + private readonly static int MAX_EVENTLOG_MESSAGE_SIZE = GetMaxEventLogMessageSize(); + + /// + /// The maximum size supported by default. + /// + /// + /// http://msdn.microsoft.com/en-us/library/xzwc042w(v=vs.100).aspx + /// The 32766 documented max size is two bytes shy of 32K (I'm assuming 32766 + /// may leave space for a two byte null terminator of #0#0). The 32766 max + /// length is what the .NET 4.0 source code checks for, but this is WRONG! + /// Strings with a length > 31839 on Windows Vista or higher can CORRUPT + /// the event log! See: System.Diagnostics.EventLogInternal.InternalWriteEvent() + /// for the use of the 32766 max size. + /// + private readonly static int MAX_EVENTLOG_MESSAGE_SIZE_DEFAULT = 32766; + + /// + /// The maximum size supported by a windows operating system that is vista + /// or newer. + /// + /// + /// See ReportEvent API: + /// http://msdn.microsoft.com/en-us/library/aa363679(VS.85).aspx + /// ReportEvent's lpStrings parameter: + /// "A pointer to a buffer containing an array of + /// null-terminated strings that are merged into the message before Event Viewer + /// displays the string to the user. This parameter must be a valid pointer + /// (or NULL), even if wNumStrings is zero. Each string is limited to 31,839 characters." + /// + /// Going beyond the size of 31839 will (at some point) corrupt the event log on Windows + /// Vista or higher! It may succeed for a while...but you will eventually run into the + /// error: "System.ComponentModel.Win32Exception : A device attached to the system is + /// not functioning", and the event log will then be corrupt (I was able to corrupt + /// an event log using a length of 31877 on Windows 7). + /// + /// The max size for Windows Vista or higher is documented here: + /// http://msdn.microsoft.com/en-us/library/xzwc042w(v=vs.100).aspx. + /// Going over this size may succeed a few times but the buffer will overrun and + /// eventually corrupt the log (based on testing). + /// + /// The maxEventMsgSize size is based on the max buffer size of the lpStrings parameter of the ReportEvent API. + /// The documented max size for EventLog.WriteEntry for Windows Vista and higher is 31839, but I'm leaving room for a + /// terminator of #0#0, as we cannot see the source of ReportEvent (though we could use an API monitor to examine the + /// buffer, given enough time). + /// + private readonly static int MAX_EVENTLOG_MESSAGE_SIZE_VISTA_OR_NEWER = 31839 - 2; + + /// + /// This method determines the maximum event log message size allowed for + /// the current environment. + /// + /// + private static int GetMaxEventLogMessageSize() + { + if (Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version.Major >= 6) + return MAX_EVENTLOG_MESSAGE_SIZE_VISTA_OR_NEWER; + return MAX_EVENTLOG_MESSAGE_SIZE_DEFAULT; + } + #endregion Private Static Fields } }