using System; using System.IO; using Microsoft.Extensions.Configuration; using Serilog; using Topshelf; using ZB.MOM.WW.LmxProxy.Host.Configuration; namespace ZB.MOM.WW.LmxProxy.Host { internal class Program { private static void Main(string[] args) { // Build configuration IConfigurationRoot? configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", true, true) .AddEnvironmentVariables() .Build(); // Configure Serilog from appsettings.json Log.Logger = new LoggerConfiguration() .ReadFrom.Configuration(configuration) .CreateLogger(); try { Log.Information("Starting ZB.MOM.WW.LmxProxy.Host"); // Load configuration var config = new LmxProxyConfiguration(); configuration.Bind(config); // Validate configuration if (!ConfigurationValidator.ValidateAndLog(config)) { Log.Fatal("Configuration validation failed. Please check the configuration and try again."); Environment.ExitCode = 1; return; } // Configure and run the Windows service using TopShelf TopshelfExitCode exitCode = HostFactory.Run(hostConfig => { hostConfig.Service(serviceConfig => { serviceConfig.ConstructUsing(() => new LmxProxyService(config)); serviceConfig.WhenStarted(service => service.Start()); serviceConfig.WhenStopped(service => service.Stop()); serviceConfig.WhenPaused(service => service.Pause()); serviceConfig.WhenContinued(service => service.Continue()); serviceConfig.WhenShutdown(service => service.Shutdown()); }); hostConfig.UseSerilog(Log.Logger); hostConfig.SetServiceName("ZB.MOM.WW.LmxProxy.Host"); hostConfig.SetDisplayName("SCADA Bridge LMX Proxy"); hostConfig.SetDescription("Provides gRPC access to Archestra MxAccess for SCADA Bridge"); hostConfig.StartAutomatically(); hostConfig.EnableServiceRecovery(recoveryConfig => { recoveryConfig.RestartService(config.ServiceRecovery.FirstFailureDelayMinutes); recoveryConfig.RestartService(config.ServiceRecovery.SecondFailureDelayMinutes); recoveryConfig.RestartService(config.ServiceRecovery.SubsequentFailureDelayMinutes); recoveryConfig.SetResetPeriod(config.ServiceRecovery.ResetPeriodDays); }); hostConfig.OnException(ex => { Log.Fatal(ex, "Unhandled exception in service"); }); }); Log.Information("Service exited with code: {ExitCode}", exitCode); Environment.ExitCode = (int)exitCode; } catch (Exception ex) { Log.Fatal(ex, "Failed to start service"); Environment.ExitCode = 1; } finally { Log.CloseAndFlush(); } } } }