📄 fileappender.cs
字号:
/// Must be called before any calls to <see cref="AcquireLock"/>,
/// <see cref="ReleaseLock"/> and <see cref="CloseFile"/>.
/// </para>
/// </remarks>
public override void OpenFile(string filename, bool append,Encoding encoding)
{
try
{
using(CurrentAppender.SecurityContext.Impersonate(this))
{
// Ensure that the directory structure exists
string directoryFullName = Path.GetDirectoryName(filename);
// Only create the directory if it does not exist
// doing this check here resolves some permissions failures
if (!Directory.Exists(directoryFullName))
{
Directory.CreateDirectory(directoryFullName);
}
FileMode fileOpenMode = append ? FileMode.Append : FileMode.Create;
m_stream = new FileStream(filename, fileOpenMode, FileAccess.Write, FileShare.Read);
}
}
catch (Exception e1)
{
CurrentAppender.ErrorHandler.Error("Unable to acquire lock on file "+filename+". "+e1.Message);
}
}
/// <summary>
/// Close the file
/// </summary>
/// <remarks>
/// <para>
/// Close the file. No further writes will be made.
/// </para>
/// </remarks>
public override void CloseFile()
{
using(CurrentAppender.SecurityContext.Impersonate(this))
{
m_stream.Close();
}
}
/// <summary>
/// Acquire the lock on the file
/// </summary>
/// <returns>A stream that is ready to be written to.</returns>
/// <remarks>
/// <para>
/// Does nothing. The lock is already taken
/// </para>
/// </remarks>
public override Stream AcquireLock()
{
return m_stream;
}
/// <summary>
/// Release the lock on the file
/// </summary>
/// <remarks>
/// <para>
/// Does nothing. The lock will be released when the file is closed.
/// </para>
/// </remarks>
public override void ReleaseLock()
{
//NOP
}
}
/// <summary>
/// Acquires the file lock for each write
/// </summary>
/// <remarks>
/// <para>
/// Opens the file once for each <see cref="AcquireLock"/>/<see cref="ReleaseLock"/> cycle,
/// thus holding the lock for the minimal amount of time. This method of locking
/// is considerably slower than <see cref="FileAppender.ExclusiveLock"/> but allows
/// other processes to move/delete the log file whilst logging continues.
/// </para>
/// </remarks>
public class MinimalLock : LockingModelBase
{
private string m_filename;
private bool m_append;
private Stream m_stream=null;
/// <summary>
/// Prepares to open the file when the first message is logged.
/// </summary>
/// <param name="filename">The filename to use</param>
/// <param name="append">Whether to append to the file, or overwrite</param>
/// <param name="encoding">The encoding to use</param>
/// <remarks>
/// <para>
/// Open the file specified and prepare for logging.
/// No writes will be made until <see cref="AcquireLock"/> is called.
/// Must be called before any calls to <see cref="AcquireLock"/>,
/// <see cref="ReleaseLock"/> and <see cref="CloseFile"/>.
/// </para>
/// </remarks>
public override void OpenFile(string filename, bool append, Encoding encoding)
{
m_filename=filename;
m_append=append;
}
/// <summary>
/// Close the file
/// </summary>
/// <remarks>
/// <para>
/// Close the file. No further writes will be made.
/// </para>
/// </remarks>
public override void CloseFile()
{
// NOP
}
/// <summary>
/// Acquire the lock on the file
/// </summary>
/// <returns>A stream that is ready to be written to.</returns>
/// <remarks>
/// <para>
/// Acquire the lock on the file in preparation for writing to it.
/// Return a stream pointing to the file. <see cref="ReleaseLock"/>
/// must be called to release the lock on the output file.
/// </para>
/// </remarks>
public override Stream AcquireLock()
{
if (m_stream==null)
{
try
{
using(CurrentAppender.SecurityContext.Impersonate(this))
{
// Ensure that the directory structure exists
string directoryFullName = Path.GetDirectoryName(m_filename);
// Only create the directory if it does not exist
// doing this check here resolves some permissions failures
if (!Directory.Exists(directoryFullName))
{
Directory.CreateDirectory(directoryFullName);
}
FileMode fileOpenMode = m_append ? FileMode.Append : FileMode.Create;
m_stream = new FileStream(m_filename, fileOpenMode, FileAccess.Write, FileShare.Read);
m_append=true;
}
}
catch (Exception e1)
{
CurrentAppender.ErrorHandler.Error("Unable to acquire lock on file "+m_filename+". "+e1.Message);
}
}
return m_stream;
}
/// <summary>
/// Release the lock on the file
/// </summary>
/// <remarks>
/// <para>
/// Release the lock on the file. No further writes will be made to the
/// stream until <see cref="AcquireLock"/> is called again.
/// </para>
/// </remarks>
public override void ReleaseLock()
{
using(CurrentAppender.SecurityContext.Impersonate(this))
{
m_stream.Close();
m_stream=null;
}
}
}
#endregion Locking Models
#region Public Instance Constructors
/// <summary>
/// Default constructor
/// </summary>
/// <remarks>
/// <para>
/// Default constructor
/// </para>
/// </remarks>
public FileAppender()
{
}
/// <summary>
/// Construct a new appender using the layout, file and append mode.
/// </summary>
/// <param name="layout">the layout to use with this appender</param>
/// <param name="filename">the full path to the file to write to</param>
/// <param name="append">flag to indicate if the file should be appended to</param>
/// <remarks>
/// <para>
/// Obsolete constructor.
/// </para>
/// </remarks>
[Obsolete("Instead use the default constructor and set the Layout, File & AppendToFile properties")]
public FileAppender(ILayout layout, string filename, bool append)
{
Layout = layout;
File = filename;
AppendToFile = append;
ActivateOptions();
}
/// <summary>
/// Construct a new appender using the layout and file specified.
/// The file will be appended to.
/// </summary>
/// <param name="layout">the layout to use with this appender</param>
/// <param name="filename">the full path to the file to write to</param>
/// <remarks>
/// <para>
/// Obsolete constructor.
/// </para>
/// </remarks>
[Obsolete("Instead use the default constructor and set the Layout & File properties")]
public FileAppender(ILayout layout, string filename) : this(layout, filename, true)
{
}
#endregion Public Instance Constructors
#region Public Instance Properties
/// <summary>
/// Gets or sets the path to the file that logging will be written to.
/// </summary>
/// <value>
/// The path to the file that logging will be written to.
/// </value>
/// <remarks>
/// <para>
/// If the path is relative it is taken as relative from
/// the application base directory.
/// </para>
/// </remarks>
virtual public string File
{
get { return m_fileName; }
set { m_fileName = value; }
}
/// <summary>
/// Gets or sets a flag that indicates whether the file should be
/// appended to or overwritten.
/// </summary>
/// <value>
/// Indicates whether the file should be appended to or overwritten.
/// </value>
/// <remarks>
/// <para>
/// If the value is set to false then the file will be overwritten, if
/// it is set to true then the file will be appended to.
/// </para>
/// The default value is true.
/// </remarks>
public bool AppendToFile
{
get { return m_appendToFile; }
set { m_appendToFile = value; }
}
/// <summary>
/// Gets or sets <see cref="Encoding"/> used to write to the file.
/// </summary>
/// <value>
/// The <see cref="Encoding"/> used to write to the file.
/// </value>
/// <remarks>
/// <para>
/// The default encoding set is <see cref="System.Text.Encoding.Default"/>
/// which is the encoding for the system's current ANSI code page.
/// </para>
/// </remarks>
public Encoding Encoding
{
get { return m_encoding; }
set { m_encoding = value; }
}
/// <summary>
/// Gets or sets the <see cref="SecurityContext"/> used to write to the file.
/// </summary>
/// <value>
/// The <see cref="SecurityContext"/> used to write to the file.
/// </value>
/// <remarks>
/// <para>
/// Unless a <see cref="SecurityContext"/> specified here for this appender
/// the <see cref="SecurityContextProvider.DefaultProvider"/> is queried for the
/// security context to use. The default behavior is to use the security context
/// of the current thread.
/// </para>
/// </remarks>
public SecurityContext SecurityContext
{
get { return m_securityContext; }
set { m_securityContext = value; }
}
/// <summary>
/// Gets or sets the <see cref="FileAppender.LockingModel"/> used to handle locking of the file.
/// </summary>
/// <value>
/// The <see cref="FileAppender.LockingModel"/> used to lock the file.
/// </value>
/// <remarks>
/// <para>
/// Gets or sets the <see cref="FileAppender.LockingModel"/> used to handle locking of the file.
/// </para>
/// <para>
/// There are two built in locking models, <see cref="FileAppender.ExclusiveLock"/> and <see cref="FileAppender.MinimalLock"/>.
/// The former locks the file from the start of logging to the end and the
/// later lock only for the minimal amount of time when logging each message.
/// </para>
/// <para>
/// The default locking model is the <see cref="FileAppender.ExclusiveLock"/>.
/// </para>
/// </remarks>
public FileAppender.LockingModelBase LockingModel
{
get { return m_lockingModel; }
set { m_lockingModel = value; }
}
#endregion Public Instance Properties
#region Override implementation of AppenderSkeleton
/// <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 FileAppender.ExclusiveLock();
}
m_lockingModel.CurrentAppender=this;
using(SecurityContext.Impersonate(this))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -