/// <summary> /// Activate the options on the file appender. /// </summary> /// <remarks> /// <para> /// This is part of the <see cref="IOptionHandler"/> delayed object /// activation scheme. The <see cref="ActivateOptions"/> method must /// be called on this object after the configuration properties have /// been set. Until <see cref="ActivateOptions"/> is called this /// object is in an undefined state and must not be used. /// </para> /// <para> /// If any of the configuration properties are modified then /// <see cref="ActivateOptions"/> must be called again. /// </para> /// <para> /// This will cause the file to be opened. /// </para> /// </remarks> override public void ActivateOptions() { base.ActivateOptions(); if (m_securityContext == null) { m_securityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this); } if (m_lockingModel == null) { m_lockingModel = new ExclusiveLock(); } m_lockingModel.CurrentAppender = this; using (SecurityContext.Impersonate(this)) { m_fileName = ConvertToFullPath(m_fileName.Trim()); } if (m_fileName != null) { SafeOpenFile(m_fileName, m_appendToFile); } else { LogLog.Warn(declaringType, "FileAppender: File option not set for appender [" + Name + "]."); LogLog.Warn(declaringType, "FileAppender: Are you using FileAppender instead of ConsoleAppender?"); } }
protected override void Append(LoggingEvent loggingEvent) { NativeError nativeError = null; // Render the event in the callers security context string renderedLoggingEvent = RenderLoggingEvent(loggingEvent); using (m_securityContext.Impersonate(this)) { // Send the message int returnValue = NetMessageBufferSend(Server, Recipient, Sender, renderedLoggingEvent, renderedLoggingEvent.Length * Marshal.SystemDefaultCharSize); // Log the error if the message could not be sent if (returnValue != 0) { // Lookup the native error nativeError = NativeError.GetError(returnValue); } } if (nativeError != null) { // Handle the error over to the ErrorHandler ErrorHandler.Error(nativeError.ToString() + " (Params: Server=" + Server + ", Recipient=" + Recipient + ", Sender=" + Sender + ")"); } }
/// <summary> /// Sets and <i>opens</i> the file where the log output will go. The specified file must be writable. /// </summary> /// <param name="fileName">The path to the log file. Must be a fully qualified path.</param> /// <param name="append">If true will append to fileName. Otherwise will truncate fileName</param> /// <remarks> /// <para> /// If there was already an opened file, then the previous file /// is closed first. /// </para> /// <para> /// This method will ensure that the directory structure /// for the <paramref name="fileName"/> specified exists. /// </para> /// </remarks> virtual protected void OpenFile(string fileName, bool append) { if (LogLog.IsErrorEnabled) { // Internal check that the fileName passed in is a rooted path bool isPathRooted = false; using (SecurityContext.Impersonate(this)) { isPathRooted = Path.IsPathRooted(fileName); } if (!isPathRooted) { LogLog.Error(declaringType, "INTERNAL ERROR. OpenFile(" + fileName + "): File name is not fully qualified."); } } lock (this) { Reset(); LogLog.Debug(declaringType, "Opening file for writing [" + fileName + "] append [" + append + "]"); // Save these for later, allowing retries if file open fails m_fileName = fileName; m_appendToFile = append; LockingModel.CurrentAppender = this; LockingModel.OpenFile(fileName, append, m_encoding); m_stream = new LockingStream(LockingModel); if (m_stream != null) { m_stream.AcquireLock(); try { SetQWForFiles(new StreamWriter(m_stream, m_encoding)); } finally { m_stream.ReleaseLock(); } } WriteHeader(); } }
/// <summary> /// This method is called by the <see cref="M:AppenderSkeleton.DoAppend(LoggingEvent)" /> /// method. /// </summary> /// <param name="loggingEvent">the event to log</param> /// <remarks> /// <para> /// Writes the event to the system event log using the /// <see cref="ApplicationName" />. /// </para> /// <para> /// If the event has an <c>EventID</c> property (see <see cref="LoggingEvent.Properties" />) /// set then this integer will be used as the event log event id. /// </para> /// <para> /// There is a limit of 32K characters for an event log message /// </para> /// </remarks> protected override void Append(LoggingEvent loggingEvent) { // // Write the resulting string to the event log system // var eventId = EventId; // Look for the EventID property var eventIdPropertyObj = loggingEvent.LookupProperty("EventID"); if (eventIdPropertyObj != null) { if (eventIdPropertyObj is int i) { eventId = i; } else { if (!(eventIdPropertyObj is string eventIdPropertyString)) { eventIdPropertyString = eventIdPropertyObj.ToString(); } if (!string.IsNullOrEmpty(eventIdPropertyString)) { // Read the string property into a number if (SystemInfo.TryParse(eventIdPropertyString, out int intVal)) { eventId = intVal; } else { ErrorHandler.Error("Unable to parse event ID property [" + eventIdPropertyString + "]."); } } } } var category = Category; // Look for the Category property var categoryPropertyObj = loggingEvent.LookupProperty("Category"); if (categoryPropertyObj != null) { if (categoryPropertyObj is short s) { category = s; } else { if (!(categoryPropertyObj is string categoryPropertyString)) { categoryPropertyString = categoryPropertyObj.ToString(); } if (!string.IsNullOrEmpty(categoryPropertyString)) { // Read the string property into a number if (SystemInfo.TryParse(categoryPropertyString, out short shortVal)) { category = shortVal; } else { ErrorHandler.Error("Unable to parse event category property [" + categoryPropertyString + "]."); } } } } // Write to the event log try { var eventTxt = RenderLoggingEvent(loggingEvent); // There is a limit of about 32K characters for an event log message if (eventTxt.Length > MaxEventlogMessageSize) { eventTxt = eventTxt.Substring(0, MaxEventlogMessageSize); } var entryType = GetEntryType(loggingEvent.Level); using (SecurityContext.Impersonate(this)) { EventLog.WriteEntry(ApplicationName, eventTxt, entryType, eventId, category); } } catch (Exception ex) { ErrorHandler.Error( "Unable to write to event log [" + LogName + "] using source [" + ApplicationName + "]", ex); } }
/// <summary> /// Initialize the appender based on the options set /// </summary> /// <remarks> /// <para> /// This is part of the <see cref="IOptionHandler" /> delayed object /// activation scheme. The <see cref="ActivateOptions" /> method must /// be called on this object after the configuration properties have /// been set. Until <see cref="ActivateOptions" /> is called this /// object is in an undefined state and must not be used. /// </para> /// <para> /// If any of the configuration properties are modified then /// <see cref="ActivateOptions" /> must be called again. /// </para> /// </remarks> public override void ActivateOptions() { try { base.ActivateOptions(); if (SecurityContext == null) { SecurityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this); } bool sourceAlreadyExists; string currentLogName = null; using (SecurityContext.Impersonate(this)) { sourceAlreadyExists = EventLog.SourceExists(ApplicationName); if (sourceAlreadyExists) { currentLogName = EventLog.LogNameFromSourceName(ApplicationName, _machineName); } } if (sourceAlreadyExists && currentLogName != LogName) { LogLog.Debug(DeclaringType, "Changing event source [" + ApplicationName + "] from log [" + currentLogName + "] to log [" + LogName + "]"); } else if (!sourceAlreadyExists) { LogLog.Debug(DeclaringType, "Creating event source Source [" + ApplicationName + "] in log " + LogName + "]"); } string registeredLogName = null; using (SecurityContext.Impersonate(this)) { if (sourceAlreadyExists && currentLogName != LogName) { // // Re-register this to the current application if the user has changed // the application / logfile association // EventLog.DeleteEventSource(ApplicationName, _machineName); CreateEventSource(ApplicationName, LogName, _machineName); registeredLogName = EventLog.LogNameFromSourceName(ApplicationName, _machineName); } else if (!sourceAlreadyExists) { CreateEventSource(ApplicationName, LogName, _machineName); registeredLogName = EventLog.LogNameFromSourceName(ApplicationName, _machineName); } } _levelMapping.ActivateOptions(); LogLog.Debug(DeclaringType, "Source [" + ApplicationName + "] is registered to log [" + registeredLogName + "]"); } catch (SecurityException ex) { ErrorHandler.Error( "Caught a SecurityException trying to access the EventLog. Most likely the event source " + ApplicationName + " doesn't exist and must be created by a local administrator. Will disable EventLogAppender." + " See http://logging.apache.org/log4net/release/faq.html#trouble-EventLog", ex); Threshold = Level.Off; } }
/// <summary> /// This method is called by the <see cref="AppenderSkeleton.DoAppend(LoggingEvent)"/> /// method. /// </summary> /// <param name="loggingEvent">the event to log</param> /// <remarks> /// <para>Writes the event to the system event log using the /// <see cref="ApplicationName"/>.</para> /// /// <para>If the event has an <c>EventID</c> property (see <see cref="LoggingEvent.Properties"/>) /// set then this integer will be used as the event log event id.</para> /// /// <para> /// There is a limit of 32K characters for an event log message /// </para> /// </remarks> override protected void Append(LoggingEvent loggingEvent) { // // Write the resulting string to the event log system // int eventID = m_eventId; // Look for the EventID property object eventIDPropertyObj = loggingEvent.LookupProperty("EventID"); if (eventIDPropertyObj != null) { if (eventIDPropertyObj is int) { eventID = (int)eventIDPropertyObj; } else { string eventIDPropertyString = eventIDPropertyObj as string; if (eventIDPropertyString == null) { eventIDPropertyString = eventIDPropertyObj.ToString(); } if (eventIDPropertyString != null && eventIDPropertyString.Length > 0) { // Read the string property into a number int intVal; if (SystemInfo.TryParse(eventIDPropertyString, out intVal)) { eventID = intVal; } else { ErrorHandler.Error("Unable to parse event ID property [" + eventIDPropertyString + "]."); } } } } short category = m_category; // Look for the Category property object categoryPropertyObj = loggingEvent.LookupProperty("Category"); if (categoryPropertyObj != null) { if (categoryPropertyObj is short) { category = (short)categoryPropertyObj; } else { string categoryPropertyString = categoryPropertyObj as string; if (categoryPropertyString == null) { categoryPropertyString = categoryPropertyObj.ToString(); } if (categoryPropertyString != null && categoryPropertyString.Length > 0) { // Read the string property into a number short shortVal; if (SystemInfo.TryParse(categoryPropertyString, out shortVal)) { category = shortVal; } else { ErrorHandler.Error("Unable to parse event category property [" + categoryPropertyString + "]."); } } } } // Write to the event log try { string eventTxt = RenderLoggingEvent(loggingEvent); // There is a limit of 32K characters for an event log message if (eventTxt.Length > 32000) { eventTxt = eventTxt.Substring(0, 32000); } EventLogEntryType entryType = GetEntryType(loggingEvent.Level); using (SecurityContext.Impersonate(this)) { EventLog.WriteEntry(m_applicationName, eventTxt, entryType, eventID, category); } } catch (Exception ex) { ErrorHandler.Error("Unable to write to event log [" + m_logName + "] using source [" + m_applicationName + "]", ex); } }