2

我们创建了一个非常简单的 ETW EventSource 实现,由语义日志记录应用程序块(通过 RollingFlatFileLogs)使用。

基本设置如下:

[EventSource(Name = "My Applicaiton")]
public partial class MyEventSource : EventSource
{
    /// <summary>
    /// The log
    /// </summary>
    public static MyEventSource Log = new MyEventSource();

...

然后,它具有基本的关键字、任务和操作码。

这些文件由如下所示的事件写入:

/// <summary>
    /// Application starting.
    /// </summary>
    [Event(100, Level = EventLevel.Verbose, Keywords = Keywords.Application, Task = Tasks.AppStart, Opcode = Opcodes.Start, Message = "Application Starting")]
    public void ApplicationStarting()
    {
        if (this.IsEnabled(EventLevel.Verbose, Keywords.Application))
        {
            this.WriteEvent(100);
        }
    }

我们使用这种方法订阅:

var listener = Microsoft.Practices.EnterpriseLibrary.SemanticLogging.RollingFlatFileLog.CreateListener("C:\\ServiceRegistry\\services.log", 5120, null, Microsoft.Practices.EnterpriseLibrary.SemanticLogging.Sinks.RollFileExistsBehavior.Increment, Microsoft.Practices.EnterpriseLibrary.SemanticLogging.Sinks.RollInterval.None, null, 10, true);

        listener.EnableEvents(MyEventSource.Log, System.Diagnostics.Tracing.EventLevel.LogAlways);


        // Log some things
        MyEventSource.Log.ApplicationStarting();

但是,我们看到的问题是一些开发人员看到锁定停止执行的日志文件。显示“文件正在使用中且无法写入”的消息。

为什么会这样?为什么即使日志记录是异步运行的,它也会结束进程?

我们如何才能防止这种情况在未来发生?有没有办法强化我们的日志记录实现,以便在出现诸如此类的错误时滚动文件?

谢谢!

编辑:我已经捕获了问题的堆栈跟踪:

 The process cannot access the file 'C:\ServiceRegistry\services.log' because it is               being used by another process.

    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
     at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
    at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy)
    at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
    at System.IO.FileInfo.Open(FileMode mode, FileAccess access, FileShare share)
    at Microsoft.Practices.EnterpriseLibrary.SemanticLogging.Sinks.RollingFlatFileSink..ctor(String fileName, Int32 rollSizeKB, String timestampPattern, RollFileExistsBehavior rollFileExistsBehavior, RollInterval rollInterval, Int32 maxArchivedFiles, Boolean isAsync)
    at Microsoft.Practices.EnterpriseLibrary.SemanticLogging.RollingFlatFileLog.CreateListener(String fileName, Int32 rollSizeKB, String timestampPattern, RollFileExistsBehavior rollFileExistsBehavior, RollInterval rollInterval, IEventTextFormatter formatter, Int32 maxArchivedFiles, Boolean isAsync)
4

1 回答 1

0

我在使用 IISExpress 进行本地开发时也遇到了同样的问题,我得到“进程无法访问文件'C:\MyPath\OurProductName.2016-01-05.log',因为它正在被另一个人使用过程。” 错误信息。如果我在 Global.asax 文件的 Application_Start 中放置一个断点,我注意到它会通过 Application_Start 运行两次。第二次是导致锁定问题的原因。我发现阻止这种情况的唯一方法是寻找我自己的唯一文件名(参见下面的代码)或在 IISExpress 中编码时关闭日志记录。

这是检查唯一文件名的例程(每次在 IISExpress 中重新编译或运行应用程序时,您将获得多个文件):

private static string GetUniqueFileName(string directoryName)
{
   string baseFileName = string.Format("OurProductName.{0}",
      DateTime.Now.ToString("yyyy-MM-dd"));
   string currentFileName = Path.Combine(directoryName, 
      string.Format("{0}.log", baseFileName));
   int number = 1;
   while (System.IO.File.Exists(currentFileName))
   {
      currentFileName = Path.Combine(directoryName, 
         string.Format("{0}.{1}.log", baseFileName, number++));
    }

    return currentFileName;
}
于 2016-01-05T18:16:10.687 回答