diff --git a/v2rayN/v2rayN/App.xaml.cs b/v2rayN/v2rayN/App.xaml.cs index 85eeed67..4ac1a638 100644 --- a/v2rayN/v2rayN/App.xaml.cs +++ b/v2rayN/v2rayN/App.xaml.cs @@ -30,14 +30,15 @@ namespace v2rayN { Global.ExePathKey = Utils.GetMD5(Utils.GetExePath()); + var rebootas = (e.Args ?? new string[] { }).Any(t => t == Global.RebootAs); ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, Global.ExePathKey, out bool bCreatedNew); - if (!bCreatedNew) + if (!rebootas && !bCreatedNew) { ProgramStarted.Set(); Current.Shutdown(); Environment.Exit(0); return; - } + } Global.processJob = new Job(); diff --git a/v2rayN/v2rayN/Global.cs b/v2rayN/v2rayN/Global.cs index 1edbe712..77239fb9 100644 --- a/v2rayN/v2rayN/Global.cs +++ b/v2rayN/v2rayN/Global.cs @@ -80,6 +80,7 @@ public const string DelayUnit = ""; public const string SpeedUnit = ""; public const int MinFontSize = 10; + public const string RebootAs = "rebootas"; public static readonly List IEProxyProtocols = new() { "{ip}:{http_port}", diff --git a/v2rayN/v2rayN/Resx/ResUI.Designer.cs b/v2rayN/v2rayN/Resx/ResUI.Designer.cs index 15d4d750..cbbc01b9 100644 --- a/v2rayN/v2rayN/Resx/ResUI.Designer.cs +++ b/v2rayN/v2rayN/Resx/ResUI.Designer.cs @@ -933,6 +933,15 @@ namespace v2rayN.Resx { } } + /// + /// 查找类似 Reboot as administrator 的本地化字符串。 + /// + public static string menuRebootAsAdmin { + get { + return ResourceManager.GetString("menuRebootAsAdmin", resourceCulture); + } + } + /// /// 查找类似 Reload 的本地化字符串。 /// diff --git a/v2rayN/v2rayN/Resx/ResUI.resx b/v2rayN/v2rayN/Resx/ResUI.resx index 7d96f263..6d8e905f 100644 --- a/v2rayN/v2rayN/Resx/ResUI.resx +++ b/v2rayN/v2rayN/Resx/ResUI.resx @@ -1153,4 +1153,7 @@ Updates are not enabled, skip this subscription + + Reboot as administrator + \ No newline at end of file diff --git a/v2rayN/v2rayN/Resx/ResUI.zh-Hans.resx b/v2rayN/v2rayN/Resx/ResUI.zh-Hans.resx index 3ff8647c..ba9fb5eb 100644 --- a/v2rayN/v2rayN/Resx/ResUI.zh-Hans.resx +++ b/v2rayN/v2rayN/Resx/ResUI.zh-Hans.resx @@ -1153,4 +1153,7 @@ 未启用更新,跳过此订阅 + + 以管理员身份重启 + \ No newline at end of file diff --git a/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs b/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs index 785678e1..4721980c 100644 --- a/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs +++ b/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs @@ -7,6 +7,7 @@ using Microsoft.Win32; using ReactiveUI; using ReactiveUI.Fody.Helpers; using Splat; +using System.Diagnostics; using System.Drawing; using System.IO; using System.Reactive; @@ -121,6 +122,7 @@ namespace v2rayN.ViewModels public ReactiveCommand OptionSettingCmd { get; } public ReactiveCommand RoutingSettingCmd { get; } public ReactiveCommand GlobalHotkeySettingCmd { get; } + public ReactiveCommand RebootAsAdminCmd { get; } public ReactiveCommand ClearServerStatisticsCmd { get; } public ReactiveCommand ImportOldGuiConfigCmd { get; } @@ -431,6 +433,10 @@ namespace v2rayN.ViewModels _noticeHandler?.Enqueue(ResUI.OperationSuccess); } }); + RebootAsAdminCmd = ReactiveCommand.Create(() => + { + RebootAsAdmin(); + }); ClearServerStatisticsCmd = ReactiveCommand.Create(() => { _statistics?.ClearAllServerStatistics(); @@ -1292,6 +1298,24 @@ namespace v2rayN.ViewModels } } + private void RebootAsAdmin() + { + ProcessStartInfo startInfo = new() + { + UseShellExecute = true, + Arguments = Global.RebootAs, + WorkingDirectory = Utils.StartupPath(), + FileName = Utils.GetExePath(), + Verb = "runas", + }; + try + { + Process.Start(startInfo); + MyAppExit(false); + } + catch { } + } + private void ImportOldGuiConfig() { OpenFileDialog fileDialog = new() diff --git a/v2rayN/v2rayN/Views/MainWindow.xaml.cs b/v2rayN/v2rayN/Views/MainWindow.xaml.cs index ea2fc4fd..3006ffe1 100644 --- a/v2rayN/v2rayN/Views/MainWindow.xaml.cs +++ b/v2rayN/v2rayN/Views/MainWindow.xaml.cs @@ -118,6 +118,7 @@ namespace v2rayN.Views this.BindCommand(ViewModel, vm => vm.OptionSettingCmd, v => v.menuOptionSetting).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.RoutingSettingCmd, v => v.menuRoutingSetting).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.GlobalHotkeySettingCmd, v => v.menuGlobalHotkeySetting).DisposeWith(disposables); + this.BindCommand(ViewModel, vm => vm.RebootAsAdminCmd, v => v.menuRebootAsAdmin).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.ClearServerStatisticsCmd, v => v.menuClearServerStatistics).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.ImportOldGuiConfigCmd, v => v.menuImportOldGuiConfig).DisposeWith(disposables);