c3b2a
c3b2a

Reputation: 3

Why cannot write log to files when WPF application publishing as a single file

I use Microsoft.Extensions.Hosting and NLog.Web.AspNetCore in WPF. The application run correctly with Debug and Release mode, But when I publish the app as a single file, I found File target does not work when fileName using relative path.

NLog version: 4.6.8
Platform: .NET Core 3
NLog config

<nlog>
  <targets>
    <default-wrapper xsi:type="BufferingWrapper" bufferSize="100"/>
    <target xsi:type="File" name="file" fileName="logs/${level}-${shortdate}.log" encoding="utf-8"
            layout="${longdate}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}" />
  </targets>
  <rules>
    <logger name="*" minlevel="Info" writeTo="file" final="true"/>
  </rules>
</nlog>

I use AddNLog to apply this configuration:

public App()
{
    _host = new HostBuilder()
        .ConfigureLogging(logBuilder =>
        {
            logBuilder.ClearProviders()
            .SetMinimumLevel(LogLevel.Debug)
            .AddNLog("NLog.config");
        })
        .ConfigureServices((hostContext, services) =>
        {
            //...
        }).Build();
}

Show the MainWindow when application startup:

private void Application_Startup(object sender, StartupEventArgs e)
{
    using var serviceScope = _host.Services.CreateScope();
    var serviceProvider = serviceScope.ServiceProvider;
    _logger = serviceProvider.GetRequiredService<ILogger<App>>();
    SetupExceptionHandling();
    MainWindow mainWindow = serviceProvider.GetRequiredService<MainWindow>();
    mainWindow.Show();
    _logger.LogInformation($"Application startup at {DateTime.Now} successfully");
}

Publishing as a single file and run it, the log of successful startup is not written to the file, But when i change fileName to an absolute path like /logs/${level}-${shortdate}.log or ${level}-${shortdate}.log, the log can be written.

I try to configure it in code:

var config = new LoggingConfiguration();
var file = new FileTarget("file")
{
    FileName = "logs/${shortdate}-${level}.log",
    Layout = "${longdate}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}"
};
config.AddRule(LogLevel.Info, LogLevel.Fatal, new BufferingTargetWrapper(file));
return config;

But the result is still the same.

Am I writing something wrong? thanks for your help.

Upvotes: 0

Views: 1159

Answers (1)

Rolf Kristensen
Rolf Kristensen

Reputation: 19867

NLog will automatically prefix relative fileName-path with the ${basedir}-layout. See also https://github.com/nlog/nlog/wiki/Basedir-Layout-Renderer

Sadly enough Microsoft decided not to fix AppDomain.BaseDirectory when doing Single File Publish in NetCore 3.1

The work-around is to explictly specify ${basedir:fixTempDir=true}:

<nlog>
  <targets>
    <default-wrapper xsi:type="BufferingWrapper" bufferSize="100"/>
    <target xsi:type="File" name="file" fileName="${basedir:fixtempdir=true}/logs/${level}-${shortdate}.log" encoding="utf-8"
            layout="${longdate}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}" />
  </targets>
  <rules>
    <logger name="*" minlevel="Info" writeTo="file" final="true"/>
  </rules>
</nlog>

Hopefully Microsoft will fix the illusion with NetCore5

Upvotes: 1

Related Questions