NLog无法使用Mono在Windows上打开文件

时间:2013-11-21 16:28:05

标签: mono servicestack nlog

我有一小组ServiceStack REST服务,它使用NLog 2.1(来自NuGet)进行日志记录。

我的测试服务器正在运行:

  • Windows 7
  • IIS 7.5
  • .NET 4.5
  • NLog config:
<nlog throwExceptions="true" internalLogToConsole="true" internalLogLevel="Debug" xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <targets>
        <target name="c" xsi:type="Console" />
        <target name="f1" xsi:type="File" fileName="C:\logs\test.log" />
    </targets>
    <rules>
        <logger name="*" writeTo="c,f1" />
    </rules>
</nlog>

我的NLog配置非常简单......只是想让它工作...... 在这种配置中,一切正常。 NLog正确创建日志文件。

在我的开发机器上,我正在使用:

  • Windows 7
  • Xamarin Studio / XSP4
  • Mono 3.2.3

这是我的Application_Start ...

protected void Application_Start() {
   LogManager.LogFactory = new NLogFactory();
   ILog log = LogManager.GetLogger(typeof(Global));
   log.Info("Application_Start called");

   try {
      new AppHost().Init();
   } catch (Exception e) {
      log.Error("Exception caught initializing AppHost");
   }
}

在此配置中,我的服务的AppHost()。Init()抛出异常,因为ServiceStack正在ServiceController.cs中注册我的服务。我相信这部分是无关紧要的,除了它是第一次在Application_Start之外记录某些东西(因为Application_Start中的两个调用都工作了......在异常之前的log.info 和log.error) 例外之后)。

以下是显示的异常:

enter image description here

最相关的一点是在NLog.Internal.FileAppenders.BaseFileAppender.WindowsCreateFile(System.String fileName,Boolean allowConcurrentWrite)中抛出了 System.NotImplementedException

我找到了一个解决方法(在下面接受的答案中)。希望遇到此问题的其他任何人都能很快找到解决方案。

1 个答案:

答案 0 :(得分:2)

Google上的一些搜索让我看到了这个NLog拉取请求:

<强> Avoid Win32-specific file functions in Mono where parts not implemented.

似乎此更改尝试使用预处理器来完全不调用WindowsCreateFile。但是,出于某种原因,这仍然会执行。

然后我去检查NLog GitHub存储库中最新版本的BaseFileAppender.cs,以确保有人在稍后的某个时间点没有再次破坏它。

#if !NET_CF && !SILVERLIGHT && !MONO
    try
        {
            if (!this.CreateFileParameters.ForceManaged && PlatformDetector.IsDesktopWin32)
            {
                return this.WindowsCreateFile(this.FileName, allowConcurrentWrite);
            }
        }
        catch (SecurityException)
        {
            InternalLogger.Debug("Could not use native Windows create file, falling back to managed filestream");
        }
#endif 
嗯......它还在那里。是什么赋予了?为什么MONO似乎不是由预处理器定义的,因此允许执行该块?我不确定。在我开始调查之前,我注意到了另一个变化......

if (!this.CreateFileParameters.ForceManaged && ...

因此,在跟踪了ForceManaged布尔回到它原点的跟踪之后,似乎我可以在我的NLog配置中的FileTarget声明上设置 forceManaged =“true”。难道真的那么简单吗?!

<nlog throwExceptions="true" internalLogToConsole="true" internalLogLevel="Debug" xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <targets>
        <target name="c" xsi:type="Console" />
        <target name="f1" xsi:type="File" forceManaged="true" fileName="C:\logs\test.log" />
    </targets>
    <rules>
        <logger name="*" writeTo="c,f1" />
    </rules>
</nlog>

一旦做出改变,一切正常......跳过了抛出异常的WindowsCreateFile调用&amp;使用了托管文件流,效果很好。哈利路亚!

最后,我无法在任何地方找到NLog文档中的forceManaged标志。如果是的话,很可能会很快找到这个解决方案。