.Net9 Web应用,Nlog在windows运行正常,部署到Linux提示ystem.NullReferenceException: Object reference not set to an instance of an object.

1. 问题

.net 9 web application,

在Programe.cs文件中的

NLog.LogManager.Configuration.Variables["configDir"] = env.ContentRootPath

这句在Windows运行正常,部署到Ubuntu 24.04 就提示

System.NullReferenceException: Object reference not set to an instance of an object.

已确认env.ContentRootPath不是Null

2. 原因分析

NLog.LogManager.Configuration为什么会是Null呢?

查看了下Nlog github上的WiKi,有如下描述(注意红色的字母

文件位置

启动时,NLog 会在各种文件中搜索其配置,如下所述。它会加载找到的第一个 nlog 配置。找到第一个 nlog 配置后,搜索结束。如果未找到配置,NLog 将不会执行任何日志记录。[加注:NLog.LogManager.Configuration null]

对于独立的 *.exe 应用程序,文件搜索如下:

  • 标准应用程序配置文件 app.config(例如 applicationname.exe.config)
  • 应用程序目录中的 applicationname.exe.nlog
  • 应用程序目录中的 NLog.config
  • NLog.dll.nlog 位于 NLog.dll 所在的目录中(仅当 NLog 未安装在 GAC 中时)

对于 ASP.NET 应用程序,文件搜索如下:

  • 标准 Web 应用程序配置文件 web.config
  • web.nlog 与 web.config 位于同一目录中
  • 应用程序目录中的 NLog.config
  • NLog.dll.nlog 位于 NLog.dll 所在的目录中(仅当 NLog 未安装在 GAC 中时)

另请参阅显式 NLog 配置加载(包括有关assetsXamarin Android 的文件夹的详细信息)。

我使用的是隐式配置加载,即没有专门的调用语句,usenlog之后就直接用了。

// NLog: Setup NLog for Dependency injection
builder.Logging.ClearProviders();
builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
builder.Logging.AddConsole();  //没有此项则控制台没有输出
builder.Host.UseNLog();

我的配置文件写的时Nlog.config,大小写错了,而linux是区分大小写的。解决这个问题走了不少弯路,也问了Gemini AI和Copilot AI,都没有很好的答案。最后看到上面这段文字才豁然开朗。

 

3. 伴生问题,路径配置

linux的路径都是"/”分割,而Windows用的是“\", 如果使用"\"在Windows上没有问题,但在Linux上就会出现生成的日志文件把路径包含进去了,比如:

MyProj\Logs\nlog-my-202412140000.log[注意:在Linux上这是一个文件名

使用"/"分割路径则在Windows和Linux上都没有问题。

    <!--write logs to file-->  
    <target xsi:type="File" name="allfile" fileName="${var:configDir}/Logs/nlog-all-${shortdate}.log"  
                 layout="${longdate}|${logger}|${uppercase:${level}}|${message} ${exception}" />  
  
    <target xsi:type="File" name="ownFile-web" fileName="${var:configDir}/Logs/nlog-my-${shortdate}.log"  
                 layout="${longdate}|${logger}|${uppercase:${level}}|${message} ${exception}" />  

4. 为什么使用env.ContentRootPath,而不是直接在NLog.config配置:baseDir

使用baseDir,在运行时会在当前程序进程所在的目录中。开发中,目录在bin/Debug/net9.0下面。

使用env.ContentRootPath,开发中目录在项目目录下,直接可见,开发查看方便一些。

5. 相关连接

https://github.com/NLog/NLog/wiki/Configuration-file

posted @ 2024-12-14 20:15  jopny  阅读(19)  评论(0编辑  收藏  举报