LumaTunnel
【WinUI】LumaTunnel 是一个面向个人多设备的 Windows 代理系统。客户端在本机提供 HTTP/HTTPS CONNECT 与 SOCKS5 TCP 代理,并通过一个受信任 TLS 证书保护的 WSS 会话,将多个 TCP 流复用到自建 Windows Server 节点。
关注
0
Fork
0
Star
0
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);
}
}
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);
}
}