From bb661d4f50d3939f625d44ec6f8a2a6df63c0ffc Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Sun, 3 Nov 2024 13:30:32 +0800 Subject: [PATCH] Only one instance is allowed to run --- v2rayN/v2rayN.Desktop/App.axaml.cs | 20 +---------- v2rayN/v2rayN.Desktop/Program.cs | 36 +++++++++++++++++-- .../v2rayN.Desktop/Views/MainWindow.axaml.cs | 10 +++--- 3 files changed, 41 insertions(+), 25 deletions(-) diff --git a/v2rayN/v2rayN.Desktop/App.axaml.cs b/v2rayN/v2rayN.Desktop/App.axaml.cs index 660e6865..ce405661 100644 --- a/v2rayN/v2rayN.Desktop/App.axaml.cs +++ b/v2rayN/v2rayN.Desktop/App.axaml.cs @@ -9,8 +9,6 @@ namespace v2rayN.Desktop; public partial class App : Application { - //public static EventWaitHandle ProgramStarted; - public override void Initialize() { if (!AppHandler.Instance.InitApp()) @@ -32,7 +30,7 @@ public partial class App : Application { if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { - OnStartup(desktop.Args); + AppHandler.Instance.InitComponents(); desktop.Exit += OnExit; desktop.MainWindow = new MainWindow(); @@ -41,22 +39,6 @@ public partial class App : Application base.OnFrameworkInitializationCompleted(); } - private void OnStartup(string[]? Args) - { - var exePathKey = Utils.GetMd5(Utils.GetExePath()); - - var rebootas = (Args ?? new string[] { }).Any(t => t == Global.RebootAs); - //ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, exePathKey, out bool bCreatedNew); - //if (!rebootas && !bCreatedNew) - //{ - // ProgramStarted.Set(); - // Environment.Exit(0); - // return; - //} - - AppHandler.Instance.InitComponents(); - } - private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { if (e.ExceptionObject != null) diff --git a/v2rayN/v2rayN.Desktop/Program.cs b/v2rayN/v2rayN.Desktop/Program.cs index 3149aab0..a5eefe42 100644 --- a/v2rayN/v2rayN.Desktop/Program.cs +++ b/v2rayN/v2rayN.Desktop/Program.cs @@ -5,12 +5,44 @@ namespace v2rayN.Desktop; internal class Program { + public static EventWaitHandle ProgramStarted; + // Initialization code. Don't use any Avalonia, third-party APIs or any // SynchronizationContext-reliant code before AppMain is called: things aren't initialized // yet and stuff might break. [STAThread] - public static void Main(string[] args) => BuildAvaloniaApp() - .StartWithClassicDesktopLifetime(args); + public static void Main(string[] args) + { + OnStartup(args); + + BuildAvaloniaApp() + .StartWithClassicDesktopLifetime(args); + } + + private static void OnStartup(string[]? Args) + { + if (Utils.IsWindows()) + { + var exePathKey = Utils.GetMd5(Utils.GetExePath()); + var rebootas = (Args ?? new string[] { }).Any(t => t == Global.RebootAs); + ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, exePathKey, out bool bCreatedNew); + if (!rebootas && !bCreatedNew) + { + ProgramStarted.Set(); + Environment.Exit(0); + return; + } + } + else + { + _ = new Mutex(true, "v2rayN", out var bOnlyOneInstance); + if (!bOnlyOneInstance) + { + Environment.Exit(0); + return; + } + } + } // Avalonia configuration, don't remove; also used by visual designer. public static AppBuilder BuildAvaloniaApp() diff --git a/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs index 5e9186e0..12cefcae 100644 --- a/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs @@ -28,9 +28,7 @@ namespace v2rayN.Desktop.Views _config = AppHandler.Instance.Config; _manager = new WindowNotificationManager(TopLevel.GetTopLevel(this)) { MaxItems = 3, Position = NotificationPosition.BottomRight }; - - //ThreadPool.RegisterWaitForSingleObject(App.ProgramStarted, OnProgramStarted, null, -1, false); - + this.Closing += MainWindow_Closing; this.KeyDown += MainWindow_KeyDown; menuSettingsSetUWP.Click += menuSettingsSetUWP_Click; @@ -114,6 +112,8 @@ namespace v2rayN.Desktop.Views this.Title = $"{Utils.GetVersion()} - {(AppHandler.Instance.IsAdministrator ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}"; if (Utils.IsWindows()) { + ThreadPool.RegisterWaitForSingleObject(Program.ProgramStarted, OnProgramStarted, null, -1, false); + menuGlobalHotkeySetting.IsVisible = false; } else @@ -158,7 +158,9 @@ namespace v2rayN.Desktop.Views private void OnProgramStarted(object state, bool timeout) { - ShowHideWindow(true); + Dispatcher.UIThread.Post(() => + ShowHideWindow(true), + DispatcherPriority.Default); } private void DelegateSnackMsg(string content)