using Microsoft.Extensions.Configuration; using Serilog; using System; using System.IO; using System.Threading; using System.Threading.Tasks; namespace RunRedis { public class Program { private static CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); public static async Task Main(string[] args) { // Configure Serilog early ConfigureSerilog(); try { Log.Information("=== Redis 管理控制台启动 ==="); Log.Information("当前工作目录: {CurrentDirectory}", Directory.GetCurrentDirectory()); Log.Information("按 'Ctrl+C' 或 'q' 键退出程序"); // Setup console cancellation Console.CancelKeyPress += (sender, e) => { e.Cancel = true; Log.Information("接收到退出信号,正在安全关闭..."); _cancellationTokenSource.Cancel(); }; // Load configuration var configuration = LoadConfiguration(); var redisSettings = new RedisSetting(); configuration.GetSection("RedisSetting").Bind(redisSettings); Log.Information("配置加载完成 - Redis服务器: {Host}:{Port}", redisSettings.Host, redisSettings.Port); // Create and run worker directly var worker = new EnhancedWorker(redisSettings); // Start monitoring for console input in background _ = Task.Run(() => MonitorConsoleInput()); // Register cancellation callback for worker _cancellationTokenSource.Token.Register(() => worker.Stop()); // Run the worker await worker.ExecuteAsync(); } catch (OperationCanceledException) { Log.Information("程序已被用户取消"); } catch (Exception ex) { Log.Fatal("程序异常终止: {Error}", ex.Message); Log.Fatal("异常详情: {Exception}", ex); } finally { Log.Information("=== Redis 管理控制台已关闭 ==="); Log.CloseAndFlush(); } } private static IConfiguration LoadConfiguration() { // Get the directory where the executable is located var baseDirectory = AppContext.BaseDirectory; return new ConfigurationBuilder() .SetBasePath(baseDirectory) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT") ?? "Production"}.json", optional: true, reloadOnChange: true) .AddEnvironmentVariables() .Build(); } private static void MonitorConsoleInput() { try { while (!_cancellationTokenSource.Token.IsCancellationRequested) { var key = Console.ReadKey(true); if (key.KeyChar == 'q' || key.KeyChar == 'Q') { Log.Information("用户按下 'q' 键,正在退出..."); _cancellationTokenSource.Cancel(); break; } } } catch (Exception ex) { Log.Warning("控制台输入监控异常: {Error}", ex.Message); } } private static void ConfigureSerilog() { // Get the directory where the executable is located var baseDirectory = AppContext.BaseDirectory; var configuration = new ConfigurationBuilder() .SetBasePath(baseDirectory) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .Build(); // Get log directory from configuration or use default var logDirectory = configuration.GetSection("RedisSetting:LogDirectory").Value ?? @"D:\SOMS\Logs\"; // Ensure log directory exists Directory.CreateDirectory(logDirectory); var logFilePath = Path.Combine(logDirectory, "RunRedis-.txt"); Log.Logger = new LoggerConfiguration() .ReadFrom.Configuration(configuration) .WriteTo.Console( outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}", theme: Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code) .WriteTo.File( logFilePath, rollingInterval: RollingInterval.Day, retainedFileCountLimit: 7, outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} {Level:u3}] {Message:lj}{NewLine}{Exception}") .MinimumLevel.Information() .Enrich.FromLogContext() .Enrich.WithProperty("Application", "Redis管理控制台") .CreateLogger(); } } }