using Microsoft.UI.Xaml; namespace LumaTunnel.Client; public partial class App : Application, IDisposable { private readonly Mutex _singleInstance; private bool _ownsMutex; public static App CurrentApp => (App)Current; public static MainWindow? MainWindow { get; private set; } public bool IsExiting { get; private set; } public App() { _singleInstance = new Mutex(true, @"Local\LumaTunnel.Client.SingleInstance", out _ownsMutex); if (!_ownsMutex) { Environment.Exit(0); return; } InitializeComponent(); UnhandledException += OnUnhandledException; AppDomain.CurrentDomain.UnhandledException += (_, _) => AppServices.SystemProxy.EmergencyRestore(); AppDomain.CurrentDomain.ProcessExit += (_, _) => AppServices.SystemProxy.EmergencyRestore(); } protected override async void OnLaunched(LaunchActivatedEventArgs args) { try { await AppServices.InitializeAsync(); MainWindow = new MainWindow(); MainWindow.Activate(); AppServices.RootNavigation.Navigate(typeof(Views.StartupLoadingPage)); AppServices.Tray.Initialize(MainWindow, MainWindow.ShowFromTray); if (Environment.GetCommandLineArgs().Contains("--background", StringComparer.OrdinalIgnoreCase)) MainWindow.AppWindow.Hide(); } catch (Exception exception) { Utilities.AppLog.Write("ERROR", "Client startup failed.", exception); AppServices.SystemProxy.EmergencyRestore(); System.Diagnostics.Debug.WriteLine(exception); Exit(); } } public async Task RequestExitAsync() { if (IsExiting) return; IsExiting = true; await AppServices.ShutdownAsync(); if (_ownsMutex) { _singleInstance.ReleaseMutex(); _ownsMutex = false; } _singleInstance.Dispose(); Exit(); } private static void OnUnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e) { System.Diagnostics.Debug.WriteLine(e.Exception); Utilities.AppLog.Write("ERROR", "Unhandled UI exception.", e.Exception); AppServices.SystemProxy.EmergencyRestore(); e.Handled = true; } public void Dispose() { if (_ownsMutex) { _singleInstance.ReleaseMutex(); _ownsMutex = false; } _singleInstance.Dispose(); GC.SuppressFinalize(this); } }