using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using RmmAgent.Services; using RmmAgent.Security; using Serilog; using Serilog.Events; namespace RmmAgent; public static class Program { public static async Task Main(string[] args) { var dataDir = Environment.GetEnvironmentVariable("RMM_DATA_DIR") ?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "RmmAgent"); Directory.CreateDirectory(dataDir); Directory.CreateDirectory(Path.Combine(dataDir, "logs")); Log.Logger = new LoggerConfiguration() .MinimumLevel.Information() .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) .MinimumLevel.Override("System.Net.Http", LogEventLevel.Warning) .Enrich.FromLogContext() .WriteTo.File( Path.Combine(dataDir, "logs", "agent-.log"), rollingInterval: RollingInterval.Day, retainedFileCountLimit: 14, fileSizeLimitBytes: 10 * 1024 * 1024, rollOnFileSizeLimit: true) .WriteTo.EventLog("RMM Agent", manageEventSource: false) .CreateLogger(); try { Log.Information("RMM Agent (PHP edition) starting up. DataDir={DataDir}", dataDir); var builder = Host.CreateApplicationBuilder(args); builder.Configuration .SetBasePath(AppContext.BaseDirectory) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddJsonFile(Path.Combine(dataDir, "appsettings.json"), optional: true, reloadOnChange: true) .AddEnvironmentVariables(prefix: "RMM_") .AddCommandLine(args); builder.Services.AddSerilog(); builder.Services.AddWindowsService(opts => { opts.ServiceName = "RmmAgent"; }); // ========== DI ========== builder.Services.AddSingleton(sp => new ConfigStore(dataDir, sp.GetRequiredService>())); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddHostedService(); var host = builder.Build(); await host.RunAsync(); return 0; } catch (Exception ex) { Log.Fatal(ex, "RMM Agent terminated unexpectedly"); return 1; } finally { await Log.CloseAndFlushAsync(); } } }