Compare commits

..

No commits in common. "514dce960a831b77f0792181000ea41913a45d6a" and "41c406b84d4bda3e2fd2fc0f827bd420dbc20e7c" have entirely different histories.

7 changed files with 132 additions and 140 deletions

View file

@ -1,7 +1,7 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<Version>7.12.0</Version> <Version>7.11.3</Version>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>

View file

@ -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;

View file

@ -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)

View file

@ -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
} }

View file

@ -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}" />

View file

@ -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>