C# 使用PublishSingleFile选项集配置NLOG

C# 使用PublishSingleFile选项集配置NLOG,c#,asp.net-core,nlog,C#,Asp.net Core,Nlog,我现在处境艰难,无法满意地解决这个问题 这些问题是由于在ASP.NET Core 3.0的Program.cs文件中使用NLOG造成的 应用程序使用中的标志PublishSingleFile发布应用程序时 Visual Studio 2019的“发布选项”对话框,带有一个自包含的应用程序 见: 如果启用此选项,发布过程将创建一个包含 所有必需的文件,包括NLOG程序集。 我部署这个独立的可执行文件 以及站点根目录中的appsettings.json和nlog.config等配置文件 以及内容文件

我现在处境艰难,无法满意地解决这个问题

这些问题是由于在ASP.NET Core 3.0的Program.cs文件中使用NLOG造成的 应用程序使用中的标志PublishSingleFile发布应用程序时 Visual Studio 2019的“发布选项”对话框,带有一个自包含的应用程序

见:

如果启用此选项,发布过程将创建一个包含 所有必需的文件,包括NLOG程序集。
我部署这个独立的可执行文件 以及站点根目录中的appsettings.json和nlog.config等配置文件 以及内容文件夹wwwroot

当启动应用程序的请求到达时,问题就会出现。 在这一点上,我在main方法的第一行得到了一个即时崩溃。 启用stdout.log文件后,我可以看到原因

未处理的异常。System.IO.FileNotFoundException:未能加载 NLog记录配置。搜索了以下位置:

  • C:\Windows\TEMP.net\MyAPI\11jsrg2n.1ad\nlog.config
文件名:“nlog.config”位于 NLog.LogFactory.LoadConfiguration(字符串配置文件,布尔可选) 在NLog.LogFactory.LoadConfiguration(字符串配置文件)处 NLog.LogManager.LoadConfiguration(字符串配置文件)位于 NLog.Web.NLogBuilder.ConfigureNLog(字符串配置文件名)位于 MyAPI.Program.Main(字符串[]args)

整个exe似乎是从与站点根文件夹不同的目录运行的

当然,这是因为我的main方法中的第一行尝试初始化NLOG程序集

要完成这个问题,这是program.cs文件中的代码

public class Program
{
    public static void Main(string[] args)
    {
        var logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
        try
        {
            logger.Info("----------------------------");
            logger.Info("MyAPI Application Start");
            CreateHostBuilder(args).Build().Run();
        }
        catch (Exception ex)
        {
            logger.Error(ex, "MyAPI stopped on Exception");
            throw;
        }
        finally
        {
            LogManager.Shutdown();
        }
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
            .ConfigureLogging(logging =>
            {
                logging.ClearProviders();
                logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Warning);
            })
            .UseNLog()
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}
公共类程序
{
公共静态void Main(字符串[]args)
{
var logger=NLogBuilder.ConfigureNLog(“nlog.config”).GetCurrentClassLogger();
尝试
{
logger.Info(“-------------------------------”;
logger.Info(“MyAPI应用程序启动”);
CreateHostBuilder(args.Build().Run();
}
捕获(例外情况除外)
{
logger.Error(例如,“MyAPI在异常时停止”);
投掷;
}
最后
{
LogManager.Shutdown();
}
}
公共静态IHostBuilder CreateHostBuilder(字符串[]args)=>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(日志=>
{
logging.ClearProviders();
logging.SetMinimumLevel(Microsoft.Extensions.logging.LogLevel.Warning);
})
.UseNLog()
.ConfigureWebHostDefaults(webBuilder=>
{
webBuilder.UseStartup();
});
}
所以,感谢所有听我解释的人,问题来了

当使用PublishSingleFile标志发布应用程序时,这是在主方法(以及启动代码)中配置NLOG的一种方法

我忘了补充一点,如果我发布时没有这个设置,一切都可以正常工作,因此这个问题不是一个问题,但是我想知道
有一种解决方法。

如果希望在单个exe文件中包含/嵌入NLog.config,请尝试在csproj文件中指定:

<Content Include="nlog.config">
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
  <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>

谢谢,我会尝试你的解决方案,但是如果我需要对nlog.config进行微调,它们会使nlog.config仍然可编辑吗?。此应用程序部署在ISP提供的宿主环境中,ISP不允许我访问根文件夹以外的文件夹或文件。因此,例如,我需要更改nlog.config中的目标路径,以指向相对于站点根目录的wwwroot/log。@tpol如果要在部署后修改
nlog.config
,则不应在单个exe文件中包含/嵌入
nlog.config
。而是将其并排部署并使用
processPath
示例。使用
processPath
示例的解决方案有效。所以你解决了我的问题。在这一点上,我仍然不确定我是否真的想使用单exe方法。是的,我要分发的文件要少得多,但启动时间似乎真的更长,在我只有少量增量修复的情况下复制一个100 MB的文件似乎使所有优势相形见绌。@tpol您可以尝试使用
true
来减小文件大小。另见NLog 4.7似乎对PublishSingleFile做了额外的调整。参见此处,他们似乎添加了一个用于指定适当日志路径的变通方法:另外:“如果希望支持覆盖NLog.config,则该文件已打包到单个文件(例如SingleApp.exe)中。”。然后必须将NLog.config重命名为SingleApp.exe.NLog。然后,NLog将优先考虑放置在实际SingleApp.exe旁边的SingleApp.exe.NLog,但将回退到secret temp文件夹中的SingleApp.exe.NLog。”
var processPath = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
var nlogConfigPath = Path.Combine(processPath, "nlog.config");
var logger = NLogBuilder.ConfigureNLog(nlogConfigPath).GetCurrentClassLogger();