Unable to specify folder in log4net when logging from window service

93 Views Asked by At

I am running a .NET Core 3.1 application as a Windows service and have added log4net logging into it. The issue I'm encountering is that it logs to the "C:/Windows/System32/Logs" folder instead of the directory where the .exe file is located. I understand that the execution path differs for Windows services, leading to logs being saved in a different location. However, is there a method to modify the folder so that it logs to the same directory as the .exe file? For all the other web applications in the solution, it logs to the same published folder.

Here is the log4net config file:

<?xml version="1.0" encoding="utf-8" ?>
<log4net>
  <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
    <file value="Logs/Logs.txt" />
    <encoding value="utf-8" />
    <appendToFile value="true" />
    <rollingStyle value="Date" />
    <maxSizeRollBackups value="10" />
    <maximumFileSize value="50MB" />
    <staticLogFileName value="true" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%-5level %date [%-5.5thread] %-40.40logger - %message%newline" />
    </layout>
  </appender>
  <root>
    <appender-ref ref="RollingFileAppender" />
    <level value="INFO" />
  </root>
</log4net>

and here is the configuration in startup.cs file:

 public IServiceProvider ConfigureServices(IServiceCollection services)
 {

     var configFilepath = Path.Combine(_env.ContentRootPath, "log4net.config");
     return services.AddAbp<EMMSubscriberModule>(
         options => options.IocManager.IocContainer.AddFacility<LoggingFacility>(
             f => f.UseAbpLog4Net().WithConfig(configFilepath)
         )
     );
 }

and the Program.cs file

 public static void Main(string[] args)
 {
     var host = BuildWebHost(args);

     if (Debugger.IsAttached || args.Contains("--debug"))
     {
         host.Run();
     }
     else
     {
         host.RunAsService();
     }
 }

 public static IWebHost BuildWebHost(string[] args)
 {
     ...

     return WebHost.CreateDefaultBuilder(args)
         .UseStartup<Startup>()
         .UseContentRoot(AppDomain.CurrentDomain.BaseDirectory)
         .Build();
 }
2

There are 2 best solutions below

1
pfx On BEST ANSWER

Set the current directory to the one where your assemblies are being found.

public static void Main(string[] args)
{
    Environment.CurrentDirectory = AppContext.BaseDirectory;

    var host = BuildWebHost(args);

    // ...
}
3
Jason Pan On

UPDATE

Using below code and it works properly in my side.

enter image description here

enter image description here

var logRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());
var appBasePath = AppDomain.CurrentDomain.BaseDirectory;
GlobalContext.Properties["LogDir"] = Path.Combine(appBasePath, "Logs");
XmlConfigurator.Configure(logRepository, new FileInfo(Path.Combine(appBasePath, "log4net.config")));

var builder = WebApplication.CreateBuilder(args);

PREVIOUS

I know you're using ABP, but the method should be the same, we need to use AppDomain.CurrentDomain.BaseDirectory to set the working path to run so that the log4net log location is valid.

public class Program
{
    public static void Main(string[] args)
    {

        string baseDir = AppDomain.CurrentDomain.BaseDirectory;
        string logDir = Path.Combine(baseDir, "Logs");
        string logPath = Path.Combine(logDir, "Logs.txt");

        if (!Directory.Exists(logDir))
        {
            Directory.CreateDirectory(logDir);
        }

        Environment.SetEnvironmentVariable("logPath", logPath);

        WebApplicationOptions options = new()
        {
            ContentRootPath = baseDir,
            Args = args,
            WebRootPath = Path.Combine(baseDir, "wwwroot")
        };

        var builder = WebApplication.CreateBuilder(options);
        ...
        app.Run();
    }
}