You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 6控制台应用托管服务安装为Windows服务后无日志输出问题

.NET 6 Windows服务Serilog日志失效排查与解决

问题描述

我有一个.NET 6.0控制台应用,启动托管服务并使用Serilog记录数据,直接运行时日志会正常输出到控制台和文件,但安装为Windows服务后,服务显示已启动,却不再生成任何日志文件。

核心原因分析

1. 配置文件路径错误

Windows服务的默认工作目录是系统目录(如C:\Windows\System32),而非程序安装目录。你在Main方法中手动加载MySettings.json和appsettings.json时,仅使用了文件名而未指定绝对路径,导致服务运行时无法找到配置文件,Serilog无法读取到文件输出的配置规则。

2. Serilog初始化冲突

你在Main开头手动初始化了Log.Logger,但后续在CreateHostBuilder中又通过.UseSerilog()重新读取配置,双重初始化可能导致配置覆盖或加载顺序异常,使得服务运行时Serilog未正确应用文件输出配置。

3. 潜在权限问题

日志路径C:\DEVSTUFF\log.txt虽在直接运行时可写入,但Windows服务默认以Local System账户运行,若该目录不存在或权限限制,也可能导致日志写入失败。

解决方案

1. 修正配置文件加载逻辑

加载配置文件时,指定程序集所在目录为基础路径,确保服务运行时能找到配置文件:

public static async Task Main(string[] args)
{
    var serviceName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
    
    // 统一使用程序目录作为配置文件基础路径
    var configBuilder = new ConfigurationBuilder()
        .SetBasePath(AppContext.BaseDirectory)
        .AddJsonFile("MySettings.json", optional: false, reloadOnChange: true)
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .Build();

    var mySettings = configBuilder.Get<MySettings>();
    var appSettings = configBuilder.Get<AppSettings>();
    var sqlConnectionString = appSettings.ConnectionString;

    Log.Information("Starting {serviceName} version {version}.", serviceName, System.Reflection.Assembly.GetExecutingAssembly().GetName().Version?.ToString());
    Log.Information("{@serviceName} microservice loading settings.", serviceName);
    
    CreateHostBuilder(args, configBuilder, appSettings, mySettings, sqlConnectionString).Build().Run();
}

2. 统一Serilog初始化方式

移除Main开头手动初始化Log.Logger的代码,让.UseSerilog()统一从配置文件加载规则,避免冲突:

public static IHostBuilder CreateHostBuilder(string[] args,
                                            IConfiguration configuration,
                                            AppSettings appSettings,
                                            MySettings mySettings,
                                            string sqlConnectionString) =>
    Host.CreateDefaultBuilder(args)
            .UseCloudMQ(context => context.UseSettings(appSettings.MQSettings))
            .UseSerilog((context, services, config) => config
                                                       .ReadFrom.Configuration(configuration)
                                                       .ReadFrom.Services(services)
                                                       .Enrich.FromLogContext())
            .UseWindowsService()
            .ConfigureServices((hostContext, services) =>
            {
                services
                   .AddTransient<ConnectorConfig>(s => appSettings.ConnectorConfig)
                   .AddTransient<IMyService, MyService>()
                   .AddTransient<IMyController, MyController>()
                   .AddTransient<IMySettings>(s => mySettings)
                   .AddSingleton<IInputOuputLogger>(new InputOuputLogger(configuration))
                   .AddDbContext<AppDbContext>(options => options.UseSqlServer(sqlConnectionString, opt => opt.UseQuerySplittingBehavior(QuerySplittingBehavior.SingleQuery)))
                   .AddHostedService<MyService>();
            });

3. 验证日志目录权限

  • 确保C:\DEVSTUFF目录存在,若不存在则手动创建
  • 检查目录权限,确保Windows服务运行账户(默认Local System)拥有读写权限,必要时可修改服务登录账户为具有明确权限的用户

4. 确保托管服务日志触发

确认MyService的日志逻辑被执行,比如在StartAsync中调用Run方法:

public Task StartAsync(CancellationToken cancellationToken)
{
    Run();
    return Task.CompletedTask;
}

补充:Serilog配置参考

你的Serilog配置本身无问题,确保配置文件被正确加载即可生效:

"serilog": {
  "Using": [
    "Serilog",
    "Serilog.Sinks.File",
    "Serilog.Sinks.Console"
  ],
  "MinimumLevel": {
    "Default": "Verbose",
    "Override": {
      "Microsoft": "Warning",
      "System": "Warning"
    }
  },
  "Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId" ],
  "WriteTo": [
    {
      "Name": "Console",
      "Args": {
        "outputTemplate": "[{Timestamp:HH:mm:ss.fff} [{Level}] {SourceContext} {Message}{NewLine}{Exception}",
        "theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console"
      }
    },
    {
      "Name": "File",
      "Args": {
        "path": "C:\\DEVSTUFF\\log.txt",
        "outputTemplate": "{Timestamp:G} {SourceContext} [{Level}] {Message}{NewLine:1}{Exception:1}",
        "formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog",
        "fileSizeLimitBytes": 1000000,
        "rollOnFileSizeLimit": "true",
        "shared": "true",
        "flushToDiskInterval": 3
      }
    }
  ]
}

内容的提问来源于stack exchange,提问作者Banshee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 10:25:38