mirror of
https://github.com/2dust/v2rayN.git
synced 2025-10-28 19:12:51 +00:00
Compare commits
3 commits
41c406b84d
...
514dce960a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
514dce960a | ||
|
|
6ee6fb1706 | ||
|
|
6985328653 |
7 changed files with 143 additions and 135 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
<Project>
|
<Project>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Version>7.11.3</Version>
|
<Version>7.12.0</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,7 +9,6 @@ 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,7 +10,6 @@ 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)
|
||||||
|
|
@ -30,69 +29,60 @@ 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)
|
||||||
{
|
{
|
||||||
try
|
var cmdLine = $"{fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetBinConfigPath(configPath).AppendQuotes())}";
|
||||||
|
var shFilePath = await CreateLinuxShellFile(cmdLine, "run_as_sudo.sh");
|
||||||
|
|
||||||
|
Process proc = new()
|
||||||
{
|
{
|
||||||
var cmdLine = $"{fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetBinConfigPath(configPath).AppendQuotes())}";
|
StartInfo = new()
|
||||||
var shFilePath = await CreateLinuxShellFile(cmdLine, "run_as_sudo.sh");
|
|
||||||
|
|
||||||
Process proc = new()
|
|
||||||
{
|
{
|
||||||
StartInfo = new()
|
FileName = shFilePath,
|
||||||
{
|
Arguments = "",
|
||||||
FileName = shFilePath,
|
WorkingDirectory = Utils.GetBinConfigPath(),
|
||||||
Arguments = "",
|
UseShellExecute = false,
|
||||||
WorkingDirectory = Utils.GetBinConfigPath(),
|
RedirectStandardInput = true,
|
||||||
UseShellExecute = false,
|
RedirectStandardOutput = true,
|
||||||
RedirectStandardInput = true,
|
RedirectStandardError = true,
|
||||||
RedirectStandardOutput = true,
|
CreateNoWindow = true,
|
||||||
RedirectStandardError = true,
|
StandardInputEncoding = Encoding.UTF8,
|
||||||
CreateNoWindow = true,
|
StandardOutputEncoding = Encoding.UTF8,
|
||||||
StandardInputEncoding = Encoding.UTF8,
|
StandardErrorEncoding = Encoding.UTF8,
|
||||||
StandardOutputEncoding = Encoding.UTF8,
|
|
||||||
StandardErrorEncoding = Encoding.UTF8,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
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();
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
_linuxSudoPid = proc.Id;
|
proc.OutputDataReceived += (sender, e) =>
|
||||||
|
|
||||||
return proc;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
{
|
||||||
Logging.SaveLog(_tag, ex);
|
if (e.Data.IsNotEmpty())
|
||||||
UpdateFunc(false, ex.Message);
|
{
|
||||||
return null;
|
UpdateFunc(false, e.Data + Environment.NewLine);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
proc.ErrorDataReceived += (sender, e) =>
|
||||||
|
{
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_linuxSudoPid = proc.Id;
|
||||||
|
|
||||||
|
return proc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task KillProcessAsLinuxSudo()
|
public async Task KillProcessAsLinuxSudo()
|
||||||
|
|
@ -102,22 +92,14 @@ public class CoreAdminHandler
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
var cmdLine = $"pkill -P {_linuxSudoPid} ; kill {_linuxSudoPid}";
|
||||||
{
|
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");
|
|
||||||
|
|
||||||
var result = await Cli.Wrap(shFilePath)
|
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,66 +238,19 @@ 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
|
||||||
{
|
{
|
||||||
Process proc = new()
|
if (mayNeedSudo
|
||||||
|
&& _config.TunModeItem.EnableTun
|
||||||
|
&& coreInfo.CoreType == ECoreType.sing_box
|
||||||
|
&& Utils.IsNonWindows())
|
||||||
{
|
{
|
||||||
StartInfo = new()
|
_linuxSudo = true;
|
||||||
{
|
await CoreAdminHandler.Instance.Init(_config, _updateFunc);
|
||||||
FileName = fileName,
|
return await CoreAdminHandler.Instance.RunProcessAsLinuxSudo(fileName, coreInfo, configPath);
|
||||||
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(500);
|
return await RunProcessNormal(fileName, coreInfo, configPath, displayLog);
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
|
@ -307,5 +260,57 @@ 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,6 +18,9 @@
|
||||||
<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>
|
||||||
|
|
@ -26,8 +29,9 @@
|
||||||
x:Name="lstGroup"
|
x:Name="lstGroup"
|
||||||
MaxHeight="200"
|
MaxHeight="200"
|
||||||
FontSize="{DynamicResource StdFontSize}"
|
FontSize="{DynamicResource StdFontSize}"
|
||||||
ItemContainerStyle="{StaticResource MyChipListBoxItem}"
|
ItemContainerStyle="{StaticResource AccessibleMyChipListBoxItem}"
|
||||||
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,7 +92,13 @@
|
||||||
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">
|
||||||
|
|
@ -184,7 +190,13 @@
|
||||||
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>
|
||||||
|
|
@ -198,7 +210,13 @@
|
||||||
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