using Avalonia; using Avalonia.Controls.ApplicationLifetimes; using Microsoft.Extensions.DependencyInjection; using OF_DL.Helpers; using OF_DL.Services; using Serilog; namespace OF_DL.Gui; public static class Program { private static int s_hasProcessedUnhandledException; public static bool HidePrivateInfo { get; private set; } public static void Main(string[] args) { try { // Parse command line arguments HidePrivateInfo = args.Contains("--hide-private-info", StringComparer.OrdinalIgnoreCase); ServiceCollection services = new(); services.AddSingleton(); ServiceProvider tempProvider = services.BuildServiceProvider(); ILoggingService loggingService = tempProvider.GetRequiredService(); RegisterGlobalExceptionHandlers(); Log.Information("Starting OF DL GUI"); // Check if running in Docker and print a message if (EnvironmentHelper.IsRunningInDocker()) { Console.WriteLine( "In your web browser, navigate to the port forwarded from your docker container. For instance, if your docker run command included \"-p 8080:8080\", open your web browser to \"http://localhost:8080\"."); } BuildAvaloniaApp() .StartWithClassicDesktopLifetime(args); } catch (Exception ex) { HandleUnhandledException(ex, "Program.Main", isTerminating: true); } finally { Log.CloseAndFlush(); } } private static AppBuilder BuildAvaloniaApp() => AppBuilder.Configure() .UsePlatformDetect() .LogToTrace(); private static void RegisterGlobalExceptionHandlers() { AppDomain.CurrentDomain.UnhandledException += (_, eventArgs) => { HandleUnhandledException(eventArgs.ExceptionObject as Exception, "AppDomain.CurrentDomain.UnhandledException", eventArgs.IsTerminating); }; TaskScheduler.UnobservedTaskException += (_, eventArgs) => { HandleUnhandledException(eventArgs.Exception, "TaskScheduler.UnobservedTaskException", isTerminating: false); eventArgs.SetObserved(); }; } private static void HandleUnhandledException(Exception? exception, string source, bool isTerminating) { if (Interlocked.Exchange(ref s_hasProcessedUnhandledException, 1) != 0) { return; } try { if (exception != null) { Log.Fatal(exception, "Unhandled exception from {Source}. Terminating={IsTerminating}", source, isTerminating); Console.WriteLine($"Unhandled exception from {source}: {exception}"); } else { Log.Fatal("Unhandled non-exception object from {Source}. Terminating={IsTerminating}", source, isTerminating); Console.WriteLine($"Unhandled non-exception object from {source}."); } } finally { Log.CloseAndFlush(); } if (!isTerminating && Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktopLifetime) { desktopLifetime.Shutdown(1); } } }