mirror of
				https://github.com/2dust/v2rayN.git
				synced 2025-10-31 04:22:51 +00:00 
			
		
		
		
	Compare commits
	
		
			No commits in common. "514dce960a831b77f0792181000ea41913a45d6a" and "41c406b84d4bda3e2fd2fc0f827bd420dbc20e7c" have entirely different histories.
		
	
	
		
			514dce960a
			...
			41c406b84d
		
	
		
					 7 changed files with 132 additions and 140 deletions
				
			
		|  | @ -1,7 +1,7 @@ | ||||||
| <Project> | <Project> | ||||||
| 
 | 
 | ||||||
|     <PropertyGroup> |     <PropertyGroup> | ||||||
|         <Version>7.12.0</Version> |         <Version>7.11.3</Version> | ||||||
|     </PropertyGroup> |     </PropertyGroup> | ||||||
| 
 | 
 | ||||||
|     <PropertyGroup> |     <PropertyGroup> | ||||||
|  |  | ||||||
|  | @ -27,4 +27,4 @@ | ||||||
|     <PackageVersion Include="YamlDotNet" Version="16.3.0" /> |     <PackageVersion Include="YamlDotNet" Version="16.3.0" /> | ||||||
|     <PackageVersion Include="ZXing.Net.Bindings.SkiaSharp" Version="0.16.14" /> |     <PackageVersion Include="ZXing.Net.Bindings.SkiaSharp" Version="0.16.14" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
| </Project> | </Project> | ||||||
|  | @ -9,6 +9,7 @@ public sealed class AppHandler | ||||||
|     private int? _statePort; |     private int? _statePort; | ||||||
|     private int? _statePort2; |     private int? _statePort2; | ||||||
|     private Job? _processJob; |     private Job? _processJob; | ||||||
|  |     private bool? _isAdministrator; | ||||||
|     public static AppHandler Instance => _instance.Value; |     public static AppHandler Instance => _instance.Value; | ||||||
|     public Config Config => _config; |     public Config Config => _config; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -10,6 +10,7 @@ public class CoreAdminHandler | ||||||
|     public static CoreAdminHandler Instance => _instance.Value; |     public static CoreAdminHandler Instance => _instance.Value; | ||||||
|     private Config _config; |     private Config _config; | ||||||
|     private Action<bool, string>? _updateFunc; |     private Action<bool, string>? _updateFunc; | ||||||
|  |     private const string _tag = "CoreAdminHandler"; | ||||||
|     private int _linuxSudoPid = -1; |     private int _linuxSudoPid = -1; | ||||||
| 
 | 
 | ||||||
|     public async Task Init(Config config, Action<bool, string> updateFunc) |     public async Task Init(Config config, Action<bool, string> updateFunc) | ||||||
|  | @ -29,60 +30,69 @@ public class CoreAdminHandler | ||||||
| 
 | 
 | ||||||
|     public async Task<Process?> RunProcessAsLinuxSudo(string fileName, CoreInfo coreInfo, string configPath) |     public async Task<Process?> RunProcessAsLinuxSudo(string fileName, CoreInfo coreInfo, string configPath) | ||||||
|     { |     { | ||||||
|         var cmdLine = $"{fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetBinConfigPath(configPath).AppendQuotes())}"; |         try | ||||||
|         var shFilePath = await CreateLinuxShellFile(cmdLine, "run_as_sudo.sh"); |  | ||||||
| 
 |  | ||||||
|         Process proc = new() |  | ||||||
|         { |         { | ||||||
|             StartInfo = new() |             var cmdLine = $"{fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetBinConfigPath(configPath).AppendQuotes())}"; | ||||||
|  |             var shFilePath = await CreateLinuxShellFile(cmdLine, "run_as_sudo.sh"); | ||||||
|  | 
 | ||||||
|  |             Process proc = new() | ||||||
|             { |             { | ||||||
|                 FileName = shFilePath, |                 StartInfo = new() | ||||||
|                 Arguments = "", |                 { | ||||||
|                 WorkingDirectory = Utils.GetBinConfigPath(), |                     FileName = shFilePath, | ||||||
|                 UseShellExecute = false, |                     Arguments = "", | ||||||
|                 RedirectStandardInput = true, |                     WorkingDirectory = Utils.GetBinConfigPath(), | ||||||
|                 RedirectStandardOutput = true, |                     UseShellExecute = false, | ||||||
|                 RedirectStandardError = true, |                     RedirectStandardInput = true, | ||||||
|                 CreateNoWindow = true, |                     RedirectStandardOutput = true, | ||||||
|                 StandardInputEncoding = Encoding.UTF8, |                     RedirectStandardError = true, | ||||||
|                 StandardOutputEncoding = Encoding.UTF8, |                     CreateNoWindow = true, | ||||||
|                 StandardErrorEncoding = Encoding.UTF8, |                     StandardInputEncoding = Encoding.UTF8, | ||||||
|             } |                     StandardOutputEncoding = Encoding.UTF8, | ||||||
|         }; |                     StandardErrorEncoding = Encoding.UTF8, | ||||||
|  |                 } | ||||||
|  |             }; | ||||||
| 
 | 
 | ||||||
|         proc.OutputDataReceived += (sender, e) => |             proc.OutputDataReceived += (sender, e) => | ||||||
|         { |  | ||||||
|             if (e.Data.IsNotEmpty()) |  | ||||||
|             { |             { | ||||||
|                 UpdateFunc(false, e.Data + Environment.NewLine); |                 if (e.Data.IsNotEmpty()) | ||||||
|             } |                 { | ||||||
|         }; |                     UpdateFunc(false, e.Data + Environment.NewLine); | ||||||
|         proc.ErrorDataReceived += (sender, e) => |                 } | ||||||
|         { |             }; | ||||||
|             if (e.Data.IsNotEmpty()) |             proc.ErrorDataReceived += (sender, e) => | ||||||
|             { |             { | ||||||
|                 UpdateFunc(false, e.Data + Environment.NewLine); |                 if (e.Data.IsNotEmpty()) | ||||||
|  |                 { | ||||||
|  |                     UpdateFunc(false, e.Data + Environment.NewLine); | ||||||
|  |                 } | ||||||
|  |             }; | ||||||
|  | 
 | ||||||
|  |             proc.Start(); | ||||||
|  |             proc.BeginOutputReadLine(); | ||||||
|  |             proc.BeginErrorReadLine(); | ||||||
|  | 
 | ||||||
|  |             await Task.Delay(10); | ||||||
|  |             await proc.StandardInput.WriteLineAsync(); | ||||||
|  |             await Task.Delay(10); | ||||||
|  |             await proc.StandardInput.WriteLineAsync(AppHandler.Instance.LinuxSudoPwd); | ||||||
|  | 
 | ||||||
|  |             await Task.Delay(100); | ||||||
|  |             if (proc is null or { HasExited: true }) | ||||||
|  |             { | ||||||
|  |                 throw new Exception(ResUI.FailedToRunCore); | ||||||
|             } |             } | ||||||
|         }; |  | ||||||
| 
 | 
 | ||||||
|         proc.Start(); |             _linuxSudoPid = proc.Id; | ||||||
|         proc.BeginOutputReadLine(); |  | ||||||
|         proc.BeginErrorReadLine(); |  | ||||||
| 
 | 
 | ||||||
|         await Task.Delay(10); |             return proc; | ||||||
|         await proc.StandardInput.WriteLineAsync(); |         } | ||||||
|         await Task.Delay(10); |         catch (Exception ex) | ||||||
|         await proc.StandardInput.WriteLineAsync(AppHandler.Instance.LinuxSudoPwd); |         { | ||||||
| 
 |             Logging.SaveLog(_tag, ex); | ||||||
|         await Task.Delay(100); |             UpdateFunc(false, ex.Message); | ||||||
|         if (proc is null or { HasExited: true }) |             return null; | ||||||
|         { |  | ||||||
|             throw new Exception(ResUI.FailedToRunCore); |  | ||||||
|         } |         } | ||||||
| 
 |  | ||||||
|         _linuxSudoPid = proc.Id; |  | ||||||
| 
 |  | ||||||
|         return proc; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public async Task KillProcessAsLinuxSudo() |     public async Task KillProcessAsLinuxSudo() | ||||||
|  | @ -92,14 +102,22 @@ public class CoreAdminHandler | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         var cmdLine = $"pkill -P {_linuxSudoPid} ; kill {_linuxSudoPid}"; |         try | ||||||
|         var shFilePath = await CreateLinuxShellFile(cmdLine, "kill_as_sudo.sh"); |         { | ||||||
|  |             var cmdLine = $"pkill -P {_linuxSudoPid} ; kill {_linuxSudoPid}"; | ||||||
|  |             var shFilePath = await CreateLinuxShellFile(cmdLine, "kill_as_sudo.sh"); | ||||||
| 
 | 
 | ||||||
|         await Cli.Wrap(shFilePath) |             var result = await Cli.Wrap(shFilePath) | ||||||
|            .WithStandardInputPipe(PipeSource.FromString(AppHandler.Instance.LinuxSudoPwd)) |                 .WithStandardInputPipe(PipeSource.FromString(AppHandler.Instance.LinuxSudoPwd)) | ||||||
|            .ExecuteAsync(); |                 .ExecuteAsync(); | ||||||
| 
 | 
 | ||||||
|         _linuxSudoPid = -1; |             _linuxSudoPid = -1; | ||||||
|  |         } | ||||||
|  |         catch (Exception ex) | ||||||
|  |         { | ||||||
|  |             Logging.SaveLog(_tag, ex); | ||||||
|  |             UpdateFunc(false, ex.Message); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private async Task<string> CreateLinuxShellFile(string cmdLine, string fileName) |     private async Task<string> CreateLinuxShellFile(string cmdLine, string fileName) | ||||||
|  |  | ||||||
|  | @ -238,19 +238,66 @@ public class CoreHandler | ||||||
|             return null; |             return null; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         if (mayNeedSudo | ||||||
|  |             && _config.TunModeItem.EnableTun | ||||||
|  |             && coreInfo.CoreType == ECoreType.sing_box | ||||||
|  |             && Utils.IsNonWindows()) | ||||||
|  |         { | ||||||
|  |             _linuxSudo = true; | ||||||
|  |             await CoreAdminHandler.Instance.Init(_config, _updateFunc); | ||||||
|  |             return await CoreAdminHandler.Instance.RunProcessAsLinuxSudo(fileName, coreInfo, configPath); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         try |         try | ||||||
|         { |         { | ||||||
|             if (mayNeedSudo |             Process proc = new() | ||||||
|                 && _config.TunModeItem.EnableTun |  | ||||||
|                 && coreInfo.CoreType == ECoreType.sing_box |  | ||||||
|                 && Utils.IsNonWindows()) |  | ||||||
|             { |             { | ||||||
|                 _linuxSudo = true; |                 StartInfo = new() | ||||||
|                 await CoreAdminHandler.Instance.Init(_config, _updateFunc); |                 { | ||||||
|                 return await CoreAdminHandler.Instance.RunProcessAsLinuxSudo(fileName, coreInfo, configPath); |                     FileName = fileName, | ||||||
|  |                     Arguments = string.Format(coreInfo.Arguments, coreInfo.AbsolutePath ? Utils.GetBinConfigPath(configPath).AppendQuotes() : configPath), | ||||||
|  |                     WorkingDirectory = Utils.GetBinConfigPath(), | ||||||
|  |                     UseShellExecute = false, | ||||||
|  |                     RedirectStandardOutput = displayLog, | ||||||
|  |                     RedirectStandardError = displayLog, | ||||||
|  |                     CreateNoWindow = true, | ||||||
|  |                     StandardOutputEncoding = displayLog ? Encoding.UTF8 : null, | ||||||
|  |                     StandardErrorEncoding = displayLog ? Encoding.UTF8 : null, | ||||||
|  |                 } | ||||||
|  |             }; | ||||||
|  | 
 | ||||||
|  |             if (displayLog) | ||||||
|  |             { | ||||||
|  |                 proc.OutputDataReceived += (sender, e) => | ||||||
|  |                 { | ||||||
|  |                     if (e.Data.IsNotEmpty()) | ||||||
|  |                     { | ||||||
|  |                         UpdateFunc(false, e.Data + Environment.NewLine); | ||||||
|  |                     } | ||||||
|  |                 }; | ||||||
|  |                 proc.ErrorDataReceived += (sender, e) => | ||||||
|  |                 { | ||||||
|  |                     if (e.Data.IsNotEmpty()) | ||||||
|  |                     { | ||||||
|  |                         UpdateFunc(false, e.Data + Environment.NewLine); | ||||||
|  |                     } | ||||||
|  |                 }; | ||||||
|  |             } | ||||||
|  |             proc.Start(); | ||||||
|  | 
 | ||||||
|  |             if (displayLog) | ||||||
|  |             { | ||||||
|  |                 proc.BeginOutputReadLine(); | ||||||
|  |                 proc.BeginErrorReadLine(); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             return await RunProcessNormal(fileName, coreInfo, configPath, displayLog); |             await Task.Delay(500); | ||||||
|  |             AppHandler.Instance.AddProcess(proc.Handle); | ||||||
|  |             if (proc is null or { HasExited: true }) | ||||||
|  |             { | ||||||
|  |                 throw new Exception(ResUI.FailedToRunCore); | ||||||
|  |             } | ||||||
|  |             return proc; | ||||||
|         } |         } | ||||||
|         catch (Exception ex) |         catch (Exception ex) | ||||||
|         { |         { | ||||||
|  | @ -260,57 +307,5 @@ public class CoreHandler | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private async Task<Process?> RunProcessNormal(string fileName, CoreInfo? coreInfo, string configPath, bool displayLog) |  | ||||||
|     { |  | ||||||
|         Process proc = new() |  | ||||||
|         { |  | ||||||
|             StartInfo = new() |  | ||||||
|             { |  | ||||||
|                 FileName = fileName, |  | ||||||
|                 Arguments = string.Format(coreInfo.Arguments, coreInfo.AbsolutePath ? Utils.GetBinConfigPath(configPath).AppendQuotes() : configPath), |  | ||||||
|                 WorkingDirectory = Utils.GetBinConfigPath(), |  | ||||||
|                 UseShellExecute = false, |  | ||||||
|                 RedirectStandardOutput = displayLog, |  | ||||||
|                 RedirectStandardError = displayLog, |  | ||||||
|                 CreateNoWindow = true, |  | ||||||
|                 StandardOutputEncoding = displayLog ? Encoding.UTF8 : null, |  | ||||||
|                 StandardErrorEncoding = displayLog ? Encoding.UTF8 : null, |  | ||||||
|             } |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         if (displayLog) |  | ||||||
|         { |  | ||||||
|             proc.OutputDataReceived += (sender, e) => |  | ||||||
|             { |  | ||||||
|                 if (e.Data.IsNotEmpty()) |  | ||||||
|                 { |  | ||||||
|                     UpdateFunc(false, e.Data + Environment.NewLine); |  | ||||||
|                 } |  | ||||||
|             }; |  | ||||||
|             proc.ErrorDataReceived += (sender, e) => |  | ||||||
|             { |  | ||||||
|                 if (e.Data.IsNotEmpty()) |  | ||||||
|                 { |  | ||||||
|                     UpdateFunc(false, e.Data + Environment.NewLine); |  | ||||||
|                 } |  | ||||||
|             }; |  | ||||||
|         } |  | ||||||
|         proc.Start(); |  | ||||||
| 
 |  | ||||||
|         if (displayLog) |  | ||||||
|         { |  | ||||||
|             proc.BeginOutputReadLine(); |  | ||||||
|             proc.BeginErrorReadLine(); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         await Task.Delay(100); |  | ||||||
|         AppHandler.Instance.AddProcess(proc.Handle); |  | ||||||
|         if (proc is null or { HasExited: true }) |  | ||||||
|         { |  | ||||||
|             throw new Exception(ResUI.FailedToRunCore); |  | ||||||
|         } |  | ||||||
|         return proc; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     #endregion Process |     #endregion Process | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -18,9 +18,6 @@ | ||||||
|     <UserControl.Resources> |     <UserControl.Resources> | ||||||
|         <BooleanToVisibilityConverter x:Key="BoolToVisConverter" /> |         <BooleanToVisibilityConverter x:Key="BoolToVisConverter" /> | ||||||
|         <conv:DelayColorConverter x:Key="DelayColorConverter" /> |         <conv:DelayColorConverter x:Key="DelayColorConverter" /> | ||||||
|         <Style x:Key="AccessibleMyChipListBoxItem" TargetType="ListBoxItem" BasedOn="{StaticResource MyChipListBoxItem}"> |  | ||||||
|             <Setter Property="AutomationProperties.Name" Value="{Binding Remarks}" /> |  | ||||||
|         </Style> |  | ||||||
|     </UserControl.Resources> |     </UserControl.Resources> | ||||||
|     <Grid> |     <Grid> | ||||||
|         <DockPanel> |         <DockPanel> | ||||||
|  | @ -29,9 +26,8 @@ | ||||||
|                     x:Name="lstGroup" |                     x:Name="lstGroup" | ||||||
|                     MaxHeight="200" |                     MaxHeight="200" | ||||||
|                     FontSize="{DynamicResource StdFontSize}" |                     FontSize="{DynamicResource StdFontSize}" | ||||||
|                     ItemContainerStyle="{StaticResource AccessibleMyChipListBoxItem}" |                     ItemContainerStyle="{StaticResource MyChipListBoxItem}" | ||||||
|                     Style="{StaticResource MaterialDesignChoiceChipPrimaryOutlineListBox}" |                     Style="{StaticResource MaterialDesignChoiceChipPrimaryOutlineListBox}"> | ||||||
|                     AutomationProperties.Name="{x:Static resx:ResUI.menuSubscription}"> |  | ||||||
|                     <ListBox.ItemTemplate> |                     <ListBox.ItemTemplate> | ||||||
|                         <DataTemplate> |                         <DataTemplate> | ||||||
|                             <TextBlock Text="{Binding Remarks}" /> |                             <TextBlock Text="{Binding Remarks}" /> | ||||||
|  |  | ||||||
|  | @ -92,13 +92,7 @@ | ||||||
|                         AutomationProperties.Name="{x:Static resx:ResUI.menuRouting}" |                         AutomationProperties.Name="{x:Static resx:ResUI.menuRouting}" | ||||||
|                         DisplayMemberPath="Remarks" |                         DisplayMemberPath="Remarks" | ||||||
|                         FontSize="{DynamicResource StdFontSize}" |                         FontSize="{DynamicResource StdFontSize}" | ||||||
|                         Style="{StaticResource MaterialDesignFloatingHintComboBox}"> |                         Style="{StaticResource MaterialDesignFloatingHintComboBox}" /> | ||||||
|                         <ComboBox.ItemContainerStyle> |  | ||||||
|                             <Style TargetType="ComboBoxItem"> |  | ||||||
|                                 <Setter Property="AutomationProperties.Name" Value="{Binding Remarks}" /> |  | ||||||
|                             </Style> |  | ||||||
|                         </ComboBox.ItemContainerStyle> |  | ||||||
|                     </ComboBox> |  | ||||||
|                 </StackPanel> |                 </StackPanel> | ||||||
| 
 | 
 | ||||||
|                 <StackPanel Margin="{StaticResource MarginLeftRight8}" VerticalAlignment="Center"> |                 <StackPanel Margin="{StaticResource MarginLeftRight8}" VerticalAlignment="Center"> | ||||||
|  | @ -190,13 +184,7 @@ | ||||||
|                                     AutomationProperties.Name="{x:Static resx:ResUI.menuRouting}" |                                     AutomationProperties.Name="{x:Static resx:ResUI.menuRouting}" | ||||||
|                                     DisplayMemberPath="Remarks" |                                     DisplayMemberPath="Remarks" | ||||||
|                                     FontSize="{DynamicResource StdFontSize}" |                                     FontSize="{DynamicResource StdFontSize}" | ||||||
|                                     Style="{StaticResource MaterialDesignFilledComboBox}"> |                                     Style="{StaticResource MaterialDesignFilledComboBox}" /> | ||||||
|                                     <ComboBox.ItemContainerStyle> |  | ||||||
|                                         <Style TargetType="ComboBoxItem"> |  | ||||||
|                                             <Setter Property="AutomationProperties.Name" Value="{Binding Remarks}" /> |  | ||||||
|                                         </Style> |  | ||||||
|                                     </ComboBox.ItemContainerStyle> |  | ||||||
|                                 </ComboBox> |  | ||||||
|                             </DockPanel> |                             </DockPanel> | ||||||
|                         </MenuItem.Header> |                         </MenuItem.Header> | ||||||
|                     </MenuItem> |                     </MenuItem> | ||||||
|  | @ -210,13 +198,7 @@ | ||||||
|                                     AutomationProperties.Name="{x:Static resx:ResUI.menuServers}" |                                     AutomationProperties.Name="{x:Static resx:ResUI.menuServers}" | ||||||
|                                     DisplayMemberPath="Text" |                                     DisplayMemberPath="Text" | ||||||
|                                     FontSize="{DynamicResource StdFontSize}" |                                     FontSize="{DynamicResource StdFontSize}" | ||||||
|                                     Style="{StaticResource MaterialDesignFilledComboBox}"> |                                     Style="{StaticResource MaterialDesignFilledComboBox}" /> | ||||||
|                                     <ComboBox.ItemContainerStyle> |  | ||||||
|                                         <Style TargetType="ComboBoxItem"> |  | ||||||
|                                             <Setter Property="AutomationProperties.Name" Value="{Binding Text}" /> |  | ||||||
|                                         </Style> |  | ||||||
|                                     </ComboBox.ItemContainerStyle> |  | ||||||
|                                 </ComboBox> |  | ||||||
|                             </DockPanel> |                             </DockPanel> | ||||||
|                         </MenuItem.Header> |                         </MenuItem.Header> | ||||||
|                     </MenuItem> |                     </MenuItem> | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue