diff --git a/v2rayN/AmazTool/UpgradeApp.cs b/v2rayN/AmazTool/UpgradeApp.cs
index 31de6a6d..852f18da 100644
--- a/v2rayN/AmazTool/UpgradeApp.cs
+++ b/v2rayN/AmazTool/UpgradeApp.cs
@@ -22,12 +22,12 @@ namespace AmazTool
Console.WriteLine("Try to end the process(尝试结束进程).");
try
{
- var path = GetPath(V2rayN);
- Console.WriteLine(path);
var existing = Process.GetProcessesByName(V2rayN);
- var pp = existing.FirstOrDefault(p => p.MainModule?.FileName != null && p.MainModule?.FileName.Contains(path) == true);
- pp?.Kill();
- pp?.WaitForExit(1000);
+ foreach (var pp in existing)
+ {
+ pp?.Kill();
+ pp?.WaitForExit(1000);
+ }
}
catch (Exception ex)
{
diff --git a/v2rayN/ServiceLib/Global.cs b/v2rayN/ServiceLib/Global.cs
index e3c974cd..90f23a56 100644
--- a/v2rayN/ServiceLib/Global.cs
+++ b/v2rayN/ServiceLib/Global.cs
@@ -46,7 +46,7 @@
public const string ClashMixinYaml = NamespaceSample + "clash_mixin_yaml";
public const string ClashTunYaml = NamespaceSample + "clash_tun_yaml";
public const string LinuxAutostartConfig = NamespaceSample + "linux_autostart_config";
-
+
public const string DefaultSecurity = "auto";
public const string DefaultNetwork = "tcp";
public const string TcpHeaderHttp = "http";
diff --git a/v2rayN/ServiceLib/Handler/AutoStartupHandler.cs b/v2rayN/ServiceLib/Handler/AutoStartupHandler.cs
index acfd3e41..42ec0086 100644
--- a/v2rayN/ServiceLib/Handler/AutoStartupHandler.cs
+++ b/v2rayN/ServiceLib/Handler/AutoStartupHandler.cs
@@ -75,7 +75,7 @@ namespace ServiceLib.Handler
{
return;
}
-
+
var logonUser = WindowsIdentity.GetCurrent().Name;
using var taskService = new Microsoft.Win32.TaskScheduler.TaskService();
var tasks = taskService.RootFolder.GetTasks(new Regex(taskName));
@@ -113,7 +113,14 @@ namespace ServiceLib.Handler
private static async Task ClearTaskLinux()
{
- File.Delete(GetHomePathLinux());
+ try
+ {
+ File.Delete(GetHomePathLinux());
+ }
+ catch (Exception ex)
+ {
+ Logging.SaveLog(ex.Message, ex);
+ }
}
private static async Task SetTaskLinux()
@@ -127,8 +134,6 @@ namespace ServiceLib.Handler
Logging.SaveLog(linuxConfig);
var homePath = GetHomePathLinux();
- Directory.CreateDirectory(Path.GetDirectoryName(homePath));
-
await File.WriteAllTextAsync(homePath, linuxConfig);
}
}
@@ -140,7 +145,9 @@ namespace ServiceLib.Handler
private static string GetHomePathLinux()
{
- return Path.Combine(Utils.GetHomePath(), ".config", "autostart", $"{Global.AppName}.desktop");
+ var homePath = Path.Combine(Utils.GetHomePath(), ".config", "autostart", $"{Global.AppName}.desktop");
+ Directory.CreateDirectory(Path.GetDirectoryName(homePath));
+ return homePath;
}
#endregion Linux
diff --git a/v2rayN/ServiceLib/Handler/ConfigHandler.cs b/v2rayN/ServiceLib/Handler/ConfigHandler.cs
index 9ecddc36..e2cc4c45 100644
--- a/v2rayN/ServiceLib/Handler/ConfigHandler.cs
+++ b/v2rayN/ServiceLib/Handler/ConfigHandler.cs
@@ -1197,7 +1197,7 @@ namespace ServiceLib.Handler
{
await RemoveServerViaSubid(config, subid, isSub);
}
-
+
profileItem.Subid = subid;
profileItem.IsSub = isSub;
profileItem.PreSocksPort = preSocksPort;
diff --git a/v2rayN/ServiceLib/Handler/CoreHandler.cs b/v2rayN/ServiceLib/Handler/CoreHandler.cs
index 8f230a18..acb91c20 100644
--- a/v2rayN/ServiceLib/Handler/CoreHandler.cs
+++ b/v2rayN/ServiceLib/Handler/CoreHandler.cs
@@ -108,13 +108,11 @@ namespace ServiceLib.Handler
{
try
{
- bool hasProc = false;
if (_process != null)
{
await KillProcess(_process);
_process.Dispose();
_process = null;
- hasProc = true;
}
if (_processPre != null)
@@ -122,26 +120,6 @@ namespace ServiceLib.Handler
await KillProcess(_processPre);
_processPre.Dispose();
_processPre = null;
- hasProc = true;
- }
-
- if (!hasProc)
- {
- var coreInfo = CoreInfoHandler.Instance.GetCoreInfo();
- foreach (var it in coreInfo)
- {
- if (it.CoreType == ECoreType.v2rayN)
- {
- continue;
- }
- foreach (var name in it.CoreExes)
- {
- var path = Utils.GetBinPath(Utils.GetExeName(name), it.CoreType.ToString());
- var existing = Process.GetProcessesByName(name);
- var pp = existing.FirstOrDefault(p => p.MainModule?.FileName != null && p.MainModule?.FileName.Contains(path) == true);
- await KillProcess(pp);
- }
- }
}
}
catch (Exception ex)
diff --git a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs
index c0d3f60e..45fdab2f 100644
--- a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs
+++ b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs
@@ -870,6 +870,15 @@ namespace ServiceLib.Resx {
}
}
+ ///
+ /// 查找类似 Are you sure to exit? 的本地化字符串。
+ ///
+ public static string menuExitTips {
+ get {
+ return ResourceManager.GetString("menuExitTips", resourceCulture);
+ }
+ }
+
///
/// 查找类似 Export selected server for complete configuration 的本地化字符串。
///
diff --git a/v2rayN/ServiceLib/Resx/ResUI.resx b/v2rayN/ServiceLib/Resx/ResUI.resx
index 93b3bcdb..2b3ea353 100644
--- a/v2rayN/ServiceLib/Resx/ResUI.resx
+++ b/v2rayN/ServiceLib/Resx/ResUI.resx
@@ -1363,4 +1363,7 @@
Install the font to the system and restart the settings
+
+ Are you sure to exit?
+
\ No newline at end of file
diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx
index 318e1239..304bb387 100644
--- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx
+++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx
@@ -1360,4 +1360,7 @@
安装字体到系统中,重启设置
+
+ 是否确定退出?
+
\ No newline at end of file
diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx
index f677ea4c..78113195 100644
--- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx
+++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx
@@ -1240,4 +1240,7 @@
安裝字體到系統中,重新啟動設定
+
+ 是否確定退出?
+
\ No newline at end of file
diff --git a/v2rayN/ServiceLib/ServiceLib.csproj b/v2rayN/ServiceLib/ServiceLib.csproj
index 75414a5c..89242b65 100644
--- a/v2rayN/ServiceLib/ServiceLib.csproj
+++ b/v2rayN/ServiceLib/ServiceLib.csproj
@@ -4,7 +4,7 @@
net8.0
enable
enable
- 7.0.5
+ 7.0.6
diff --git a/v2rayN/ServiceLib/Services/SpeedtestService.cs b/v2rayN/ServiceLib/Services/SpeedtestService.cs
index d8411903..e257d421 100644
--- a/v2rayN/ServiceLib/Services/SpeedtestService.cs
+++ b/v2rayN/ServiceLib/Services/SpeedtestService.cs
@@ -2,6 +2,7 @@
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
+
namespace ServiceLib.Services
{
public class SpeedtestService
@@ -85,7 +86,7 @@ namespace ServiceLib.Services
private void ExitLoop(string x)
{
- if(_exitLoop) return;
+ if (_exitLoop) return;
_exitLoop = true;
UpdateFunc("", ResUI.SpeedtestingStop);
}
diff --git a/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs b/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs
index 5fc22623..79f2d29f 100644
--- a/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs
+++ b/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs
@@ -52,6 +52,8 @@ namespace ServiceLib.ViewModels
public ReactiveCommand ReloadCmd { get; }
+ public ReactiveCommand ExitCmd { get; }
+
[Reactive]
public bool BlReloadEnabled { get; set; }
@@ -187,6 +189,11 @@ namespace ServiceLib.ViewModels
await Reload();
});
+ ExitCmd = ReactiveCommand.CreateFromTask(async () =>
+ {
+ await Exit();
+ });
+
RegionalPresetDefaultCmd = ReactiveCommand.CreateFromTask(async () =>
{
await ApplyRegionalPreset(EPresetType.Default);
@@ -266,7 +273,7 @@ namespace ServiceLib.ViewModels
try
{
Locator.Current.GetService()?.UpdateStatistics(update);
- if ((update.ProxyUp + update.ProxyDown) > 0 && DateTime.Now.Second % 3 == 0)
+ if ((update.ProxyUp + update.ProxyDown) > 0 && DateTime.Now.Second % 9 == 0)
{
Locator.Current.GetService()?.UpdateStatistics(update);
}
@@ -289,7 +296,7 @@ namespace ServiceLib.ViewModels
await ProfileExHandler.Instance.SaveTo();
await StatisticsHandler.Instance.SaveTo();
StatisticsHandler.Instance.Close();
- CoreHandler.Instance.CoreStop();
+ await CoreHandler.Instance.CoreStop();
Logging.SaveLog("MyAppExit End");
}
@@ -588,6 +595,16 @@ namespace ServiceLib.ViewModels
}
}
+ private async Task Exit()
+ {
+ if (await _updateView?.Invoke(EViewAction.ShowYesNo, null) == false)
+ {
+ return;
+ }
+
+ await MyAppExitAsync(false);
+ }
+
#endregion core job
#region Presets
diff --git a/v2rayN/ServiceLib/ViewModels/ProfilesViewModel.cs b/v2rayN/ServiceLib/ViewModels/ProfilesViewModel.cs
index 66d38ddc..507fff0e 100644
--- a/v2rayN/ServiceLib/ViewModels/ProfilesViewModel.cs
+++ b/v2rayN/ServiceLib/ViewModels/ProfilesViewModel.cs
@@ -686,7 +686,6 @@ namespace ServiceLib.ViewModels
//ClearTestResult();
_ = new SpeedtestService(_config, lstSelecteds, actionType, UpdateSpeedtestHandler);
-
}
public void ServerSpeedtestStop()
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 b/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml
index 6dd66d40..d927b846 100644
--- a/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml
+++ b/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml
@@ -114,7 +114,7 @@
diff --git a/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs
index 5e9186e0..d8e7867e 100644
--- a/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs
+++ b/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs
@@ -7,6 +7,7 @@ using Avalonia.Interactivity;
using Avalonia.ReactiveUI;
using Avalonia.Threading;
using DialogHostAvalonia;
+using MsBox.Avalonia.Enums;
using ReactiveUI;
using Splat;
using System.ComponentModel;
@@ -29,13 +30,10 @@ 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;
menuPromotion.Click += menuPromotion_Click;
- menuClose.Click += menuClose_Click;
menuCheckUpdate.Click += MenuCheckUpdate_Click;
menuBackupAndRestore.Click += MenuBackupAndRestore_Click;
@@ -82,6 +80,7 @@ namespace v2rayN.Desktop.Views
this.BindCommand(ViewModel, vm => vm.ReloadCmd, v => v.menuReload).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.BlReloadEnabled, v => v.menuReload.IsEnabled).DisposeWith(disposables);
+ this.BindCommand(ViewModel, vm => vm.ExitCmd, v => v.menuClose).DisposeWith(disposables);
switch (_config.UiItem.MainGirdOrientation)
{
@@ -114,6 +113,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 +159,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)
@@ -240,6 +243,14 @@ namespace v2rayN.Desktop.Views
Locator.Current.GetService()?.AutofitColumnWidthAsync(),
DispatcherPriority.Default);
break;
+
+ case EViewAction.ShowYesNo:
+ if (await UI.ShowYesNo(this, ResUI.menuExitTips) == ButtonResult.No)
+ {
+ return false;
+ }
+ StorageUI();
+ break;
}
return await Task.FromResult(true);
@@ -302,12 +313,6 @@ namespace v2rayN.Desktop.Views
}
}
- private void menuClose_Click(object? sender, RoutedEventArgs e)
- {
- StorageUI();
- ShowHideWindow(false);
- }
-
private void menuPromotion_Click(object? sender, RoutedEventArgs e)
{
Utils.ProcessStart($"{Utils.Base64Decode(Global.PromotionUrl)}?t={DateTime.Now.Ticks}");
@@ -374,8 +379,16 @@ namespace v2rayN.Desktop.Views
}
else
{
- this.Hide();
+ if (Utils.IsWindows())
+ {
+ this.Hide();
+ }
+ else
+ {
+ this.WindowState = WindowState.Minimized;
+ }
}
+
_config.UiItem.ShowInTaskbar = bl;
}
diff --git a/v2rayN/v2rayN.Desktop/Views/OptionSettingWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/OptionSettingWindow.axaml.cs
index 66026a6a..5fea12c0 100644
--- a/v2rayN/v2rayN.Desktop/Views/OptionSettingWindow.axaml.cs
+++ b/v2rayN/v2rayN.Desktop/Views/OptionSettingWindow.axaml.cs
@@ -174,7 +174,7 @@ namespace v2rayN.Desktop.Views
{
switch (action)
{
- case EViewAction.CloseWindow:
+ case EViewAction.CloseWindow:
this.Close(true);
break;
diff --git a/v2rayN/v2rayN/Views/MainWindow.xaml.cs b/v2rayN/v2rayN/Views/MainWindow.xaml.cs
index c323486b..e9a18a73 100644
--- a/v2rayN/v2rayN/Views/MainWindow.xaml.cs
+++ b/v2rayN/v2rayN/Views/MainWindow.xaml.cs
@@ -367,17 +367,17 @@ namespace v2rayN.Views
var bl = blShow ?? !_config.UiItem.ShowInTaskbar;
if (bl)
{
- Application.Current.MainWindow.Show();
- if (Application.Current.MainWindow.WindowState == WindowState.Minimized)
+ this?.Show();
+ if (this?.WindowState == WindowState.Minimized)
{
- Application.Current.MainWindow.WindowState = WindowState.Normal;
+ this.WindowState = WindowState.Normal;
}
- Application.Current.MainWindow.Activate();
- Application.Current.MainWindow.Focus();
+ this?.Activate();
+ this?.Focus();
}
else
{
- Application.Current.MainWindow.Hide();
+ this?.Hide();
}
_config.UiItem.ShowInTaskbar = bl;
}