From df84ad4271f3954aafaf97502ee43412e81d49ea Mon Sep 17 00:00:00 2001 From: Aigio Liu Date: Mon, 29 May 2023 12:09:46 +0800 Subject: [PATCH 1/6] =?UTF-8?q?=E2=9C=A8=20Impl=20-clt=20plugins=20-l=20{A?= =?UTF-8?q?ppServicesLevel}=20-m=20{=E6=8F=92=E4=BB=B6=E5=90=8D}=20-n=20{P?= =?UTF-8?q?ipeName}=20-p=20{ProcessId}=20-a=20{=E6=8F=92=E4=BB=B6=E9=9C=80?= =?UTF-8?q?=E8=A6=81=E8=A7=A3=E6=9E=90=E7=9A=84=E5=8F=82=E6=95=B0}?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/IPCSubProcessService.cs | 18 ++- .../Plugins/Abstractions/IPlugin.cs | 12 ++ .../Plugins/Abstractions/PluginBase.cs | 43 +++++++ src/BD.WTTS.Client/Plugins/PluginsCore.cs | 64 ++++++++--- .../IPC/IPCMainProcessServiceImpl.cs | 27 ++--- .../ScheduledTaskServiceImpl.PowerShell.cs | 5 +- .../Windows/ScheduledTaskServiceImpl.cs | 4 +- .../WindowsPlatformServiceImpl.BypassUAC.cs | 28 +++-- .../WindowsPlatformServiceImpl.SystemOnOff.cs | 2 +- .../Windows/WindowsPlatformServiceImpl.cs | 3 +- .../IPlatformService.IsAdministrator.cs | 28 ++--- .../Platform/Windows/IScheduledTaskService.cs | 3 +- .../Startup/Startup.Commands.cs | 105 ++++++++++++++++-- src/BD.WTTS.Client/Startup/Startup.Host.cs | 7 +- 14 files changed, 264 insertions(+), 85 deletions(-) diff --git a/src/BD.WTTS.Client.IPC/Services/IPCSubProcessService.cs b/src/BD.WTTS.Client.IPC/Services/IPCSubProcessService.cs index ba9f0f60b..8f08309f6 100644 --- a/src/BD.WTTS.Client.IPC/Services/IPCSubProcessService.cs +++ b/src/BD.WTTS.Client.IPC/Services/IPCSubProcessService.cs @@ -1,4 +1,5 @@ using dotnetCampus.Ipc.Pipes; +using ExitCode = BD.WTTS.Startup.CommandExitCode; namespace BD.WTTS.Services; @@ -24,11 +25,6 @@ public interface IPCSubProcessService : IDisposable /// T? GetService() where T : class; - const int ExitCode_EmptyArrayArgs = 4001; - const int ExitCode_EmptyPipeName = 4002; - const int ExitCode_EmptyMainProcessId = 4003; - const int ExitCode_NotFoundMainProcessId = 4004; - private static IPCSubProcessServiceImpl? iPCSubProcessServiceImpl; static IPCSubProcessService Instance => iPCSubProcessServiceImpl.ThrowIsNull(); @@ -37,8 +33,8 @@ public interface IPCSubProcessService : IDisposable /// 子进程 IPC 程序启动通用函数 /// /// - /// - /// + /// 配置子进程的依赖注入服务 + /// 配置 IPC 服务 /// /// static async Task MainAsync( @@ -48,15 +44,15 @@ public interface IPCSubProcessService : IDisposable params string[] args) { if (args.Length < 2) - return ExitCode_EmptyArrayArgs; + return (int)ExitCode.EmptyArrayArgs; var pipeName = args[0]; if (string.IsNullOrWhiteSpace(pipeName)) - return ExitCode_EmptyPipeName; + return (int)ExitCode.EmptyPipeName; if (!int.TryParse(args[1], out var pid)) - return ExitCode_EmptyMainProcessId; + return (int)ExitCode.EmptyMainProcessId; var mainProcess = Process.GetProcessById(pid); if (mainProcess == null) - return ExitCode_NotFoundMainProcessId; + return (int)ExitCode.NotFoundMainProcessId; TaskCompletionSource tcs = new(); mainProcess.EnableRaisingEvents = true; diff --git a/src/BD.WTTS.Client/Plugins/Abstractions/IPlugin.cs b/src/BD.WTTS.Client/Plugins/Abstractions/IPlugin.cs index 00fb9bd08..e169313f3 100644 --- a/src/BD.WTTS.Client/Plugins/Abstractions/IPlugin.cs +++ b/src/BD.WTTS.Client/Plugins/Abstractions/IPlugin.cs @@ -1,3 +1,5 @@ +using dotnetCampus.Ipc.Pipes; + namespace BD.WTTS.Plugins.Abstractions; /// @@ -69,4 +71,14 @@ public interface IPlugin : IExplicitHasValue void OnUnhandledException(Exception ex, string name, bool? isTerminating = null); ValueTask OnExit(); + + /// + /// 启动子进程 IPC 程序的 Main 函数 + /// + /// + /// + /// + /// + /// + Task RunSubProcessMainAsync(string moduleName, string pipeName, string processId, string encodedArgs); } diff --git a/src/BD.WTTS.Client/Plugins/Abstractions/PluginBase.cs b/src/BD.WTTS.Client/Plugins/Abstractions/PluginBase.cs index 94fa7151b..36d293256 100644 --- a/src/BD.WTTS.Client/Plugins/Abstractions/PluginBase.cs +++ b/src/BD.WTTS.Client/Plugins/Abstractions/PluginBase.cs @@ -1,3 +1,5 @@ +using dotnetCampus.Ipc.Pipes; + namespace BD.WTTS.Plugins.Abstractions; [DebuggerDisplay("{DebuggerDisplay,nq}")] @@ -68,4 +70,45 @@ public abstract class PluginBase : IPlugin where TPlugin : PluginBase + /// 将参数解析为字符串 + /// + /// + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected static string DecodeArgs(string args) + => HttpUtility.UrlDecode(args); + + /// + /// 将参数解析为字符串数组 + /// + /// + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected static string[] DecodeToArrayArgs(string args) + => HttpUtility.UrlDecode(args).Split(' ', StringSplitOptions.RemoveEmptyEntries); + + public virtual async Task RunSubProcessMainAsync(string moduleName, string pipeName, string processId, string encodedArgs) + { + var subProcessBootConfiguration = GetSubProcessBootConfiguration(encodedArgs ?? string.Empty); + if (subProcessBootConfiguration == default) + return (int)Startup.CommandExitCode.GetSubProcessBootConfigurationFail; + + var exitCode = await IPCSubProcessService.MainAsync(moduleName, + subProcessBootConfiguration.configureServices, + subProcessBootConfiguration.configureIpcProvider, + new[] { pipeName, processId }); + return exitCode; + } + + /// + /// 获取子进程 IPC 程序启动配置 + /// + /// + /// + protected virtual (Action? configureServices, Action? configureIpcProvider) GetSubProcessBootConfiguration(string args) + { + return default; + } } diff --git a/src/BD.WTTS.Client/Plugins/PluginsCore.cs b/src/BD.WTTS.Client/Plugins/PluginsCore.cs index fc04311fd..d4b05d400 100644 --- a/src/BD.WTTS.Client/Plugins/PluginsCore.cs +++ b/src/BD.WTTS.Client/Plugins/PluginsCore.cs @@ -7,20 +7,28 @@ public static class PluginsCore static readonly HashSet ignoreDirNames = new(StringComparer.OrdinalIgnoreCase) { - "Update", + Update, }; - internal static HashSet? LoadAssemblies() + public const string Accelerator = "Accelerator"; + public const string GameAccount = "GameAccount"; + public const string GameList = "GameList"; + public const string ArchiSteamFarmPlus = "ArchiSteamFarmPlus"; + public const string Authenticator = "Authenticator"; + public const string GameTools = "GameTools"; + public const string Update = "Update"; + + internal static HashSet? LoadAssemblies(params string[] loadModules) { HashSet? assemblies = null; #if DEBUG // DEBUG 模式遍历项目查找模块 - var modules = new[] { - "Accelerator", - "GameAccount", - "GameList", - "ArchiSteamFarmPlus", - "Authenticator", - "GameTools", + var modules = loadModules.Any_Nullable() ? loadModules : new[] { + Accelerator, + GameAccount, + GameList, + ArchiSteamFarmPlus, + Authenticator, + GameTools, }; foreach (var item in modules) { @@ -70,12 +78,12 @@ public static class PluginsCore var pluginsPath = Path.Combine(AppContext.BaseDirectory, "modules"); if (Directory.Exists(pluginsPath)) { - var directories = Directory.EnumerateDirectories(pluginsPath); - foreach (var directory in directories) + bool EachDirectories(string directory, string? dirName = null) { - var dirName = Path.GetDirectoryName(directory); - if (dirName == null) continue; - if (ignoreDirNames.Contains(dirName)) continue; + dirName ??= Path.GetDirectoryName(directory); + if (dirName == null) return true; + if (ignoreDirNames.Contains(dirName)) + return true; var dllPath = Path.Combine(directory, $"Steam++.Plugins.{dirName}.dll"); if (File.Exists(dllPath)) @@ -90,13 +98,35 @@ public static class PluginsCore catch (Exception e) { Log.Error(TAG, e, $"AssemblyLoadFrom fail, assemblyPath: {assemblyPath}"); - continue; + return true; } assemblies ??= new(); assemblies.Add(assembly); } } + return false; + } + + if (loadModules.Any_Nullable()) + { + foreach (var loadModule in loadModules) + { + var directory = Path.Combine(pluginsPath, loadModule); + if (!Directory.Exists(directory)) + continue; + if (EachDirectories(directory, loadModule)) + continue; + } + } + else + { + var directories = Directory.EnumerateDirectories(pluginsPath); + foreach (var directory in directories) + { + if (EachDirectories(directory)) + continue; + } } } #endif @@ -122,9 +152,9 @@ public static class PluginsCore } } - internal static HashSet? InitPlugins() + internal static HashSet? InitPlugins(params string[] loadModules) { - HashSet? assemblies = LoadAssemblies(); + HashSet? assemblies = LoadAssemblies(loadModules); if (!assemblies.Any_Nullable()) return null; var assemblies_ = VerifyAssemblies(assemblies).ToArray(); diff --git a/src/BD.WTTS.Client/Services.Implementation/IPC/IPCMainProcessServiceImpl.cs b/src/BD.WTTS.Client/Services.Implementation/IPC/IPCMainProcessServiceImpl.cs index e1986bc41..226eb0c17 100644 --- a/src/BD.WTTS.Client/Services.Implementation/IPC/IPCMainProcessServiceImpl.cs +++ b/src/BD.WTTS.Client/Services.Implementation/IPC/IPCMainProcessServiceImpl.cs @@ -178,24 +178,21 @@ public sealed partial class IPCMainProcessServiceImpl : IPCMainProcessService #if WINDOWS // 启动管理员权限服务进程 - if (IPlatformService.Instance is WindowsPlatformServiceImpl windowsPlatformService) + Task2.InBackground(async () => { - Task2.InBackground(async () => + var processPath = Environment.ProcessPath; + processPath.ThrowIsNull(); + var pipeName = ipcProvider.ThrowIsNull().IpcContext.PipeName; + const string arguments_ = + $"-clt {IPlatformService.IPCRoot.CommandName} {IPlatformService.IPCRoot.args_PipeName} {{0}} {IPlatformService.IPCRoot.args_ProcessId} {{1}}"; + var arguments = string.Format(arguments_, pipeName, pid); + await AddDaemonWithStartSubProcessAsync(IPlatformService.IPCRoot.moduleName, async _ => { - var processPath = Environment.ProcessPath; - processPath.ThrowIsNull(); - var pipeName = ipcProvider.ThrowIsNull().IpcContext.PipeName; - const string arguments_ = - $"-clt {IPlatformService.IPCRoot.CommandName} {IPlatformService.IPCRoot.args_PipeName} {{0}} {IPlatformService.IPCRoot.args_ProcessId} {{1}}"; - var arguments = string.Format(arguments_, pipeName, pid); - await AddDaemonWithStartSubProcessAsync(IPlatformService.IPCRoot.moduleName, async _ => - { - var process = await windowsPlatformService.StartAsAdministrator(processPath, arguments); - return process; - }); - await IPlatformService.IPCRoot.SetIPC(this); + var process = await WindowsPlatformServiceImpl.StartAsAdministrator(processPath, arguments); + return process; }); - } + await IPlatformService.IPCRoot.SetIPC(this); + }); #endif } diff --git a/src/BD.WTTS.Client/Services.Implementation/Platform/Windows/ScheduledTaskServiceImpl.PowerShell.cs b/src/BD.WTTS.Client/Services.Implementation/Platform/Windows/ScheduledTaskServiceImpl.PowerShell.cs index 69136eb94..68734910a 100644 --- a/src/BD.WTTS.Client/Services.Implementation/Platform/Windows/ScheduledTaskServiceImpl.PowerShell.cs +++ b/src/BD.WTTS.Client/Services.Implementation/Platform/Windows/ScheduledTaskServiceImpl.PowerShell.cs @@ -13,14 +13,13 @@ partial class ScheduledTaskServiceImpl /// 使用 PowerShell 实现的开机启动 /// https://docs.microsoft.com/en-us/powershell/module/scheduledtasks /// - /// /// /// /// /// /// /// - static async void SetBootAutoStartByPowerShell(IPlatformService platformService, bool isAutoStart, string name, string userId, string userName, string tdName, string programName) + static async void SetBootAutoStartByPowerShell(bool isAutoStart, string name, string userId, string userName, string tdName, string programName) { if (isAutoStart) { @@ -32,7 +31,7 @@ partial class ScheduledTaskServiceImpl if (string.IsNullOrWhiteSpace(userName)) userName = userId; else userName = SecurityElement.Escape(userName); var description = SecurityElement.Escape(GetDescription(name)); - var xml = $"{description}true{userName}{userId}InteractiveToken{(platformService.IsAdministrator ? "HighestAvailable" : "LeastPrivilege")}IgnoreNewfalsefalsefalsefalsefalsePT10MPT1HtruefalsetruetruefalsefalsefalsePT0S5{programName}{arguments}{workingDirectory}"; + var xml = $"{description}true{userName}{userId}InteractiveToken{(IPlatformService._IsAdministrator.Value ? "HighestAvailable" : "LeastPrivilege")}IgnoreNewfalsefalsefalsefalsefalsePT10MPT1HtruefalsetruetruefalsefalsefalsePT0S5{programName}{arguments}{workingDirectory}"; await RunPowerShellSinglePipeAsync($"Register-ScheduledTask -Force -TaskName '{Escape(tdName)}' -Xml '{Escape(xml)}';exit"); } else diff --git a/src/BD.WTTS.Client/Services.Implementation/Platform/Windows/ScheduledTaskServiceImpl.cs b/src/BD.WTTS.Client/Services.Implementation/Platform/Windows/ScheduledTaskServiceImpl.cs index ceb9bbefa..569b6517e 100644 --- a/src/BD.WTTS.Client/Services.Implementation/Platform/Windows/ScheduledTaskServiceImpl.cs +++ b/src/BD.WTTS.Client/Services.Implementation/Platform/Windows/ScheduledTaskServiceImpl.cs @@ -6,7 +6,7 @@ namespace BD.WTTS.Services.Implementation; sealed partial class ScheduledTaskServiceImpl : IScheduledTaskService { - void IScheduledTaskService.SetBootAutoStart(IPlatformService platformService, bool isAutoStart, string name) + void IScheduledTaskService.SetBootAutoStart(bool isAutoStart, string name) { try { @@ -16,7 +16,7 @@ sealed partial class ScheduledTaskServiceImpl : IScheduledTaskService var userId = hasSid ? identity.User!.ToString() : userName; var tdName = hasSid ? userId : userId.Replace(Path.DirectorySeparatorChar, '_'); tdName = $"{name}_{{{tdName}}}"; - SetBootAutoStartByPowerShell(platformService, isAutoStart, name, userId, userName, tdName, IApplication.ProgramName); + SetBootAutoStartByPowerShell(isAutoStart, name, userId, userName, tdName, IApplication.ProgramName); } catch (Exception e) { diff --git a/src/BD.WTTS.Client/Services.Implementation/Platform/Windows/WindowsPlatformServiceImpl.BypassUAC.cs b/src/BD.WTTS.Client/Services.Implementation/Platform/Windows/WindowsPlatformServiceImpl.BypassUAC.cs index 13cc53fd6..e2175f46e 100644 --- a/src/BD.WTTS.Client/Services.Implementation/Platform/Windows/WindowsPlatformServiceImpl.BypassUAC.cs +++ b/src/BD.WTTS.Client/Services.Implementation/Platform/Windows/WindowsPlatformServiceImpl.BypassUAC.cs @@ -44,7 +44,7 @@ partial class WindowsPlatformServiceImpl /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static async Task StartAsAdministratorByBypassUAC(string fileName, string? arguments = null) + internal static async Task StartAsAdministratorByBypassUAC(string fileName, string? arguments = null) { /** 33. Author: winscripting.blog * https://github.com/hfiref0x/UACME @@ -68,6 +68,15 @@ partial class WindowsPlatformServiceImpl if (!File.Exists(targetName)) return null; + var processPath = Environment.ProcessPath; + processPath.ThrowIsNull(); + if (fileName != processPath) // 仅允许启动自己 + throw new ArgumentOutOfRangeException(nameof(fileName)); + + var processName = Path.GetFileNameWithoutExtension(fileName); + if (string.IsNullOrWhiteSpace(processName)) + throw new ArgumentNullException(nameof(processName)); + classes = Registry.CurrentUser.OpenSubKey(@"Software\Classes", true); using var command = classes!.CreateSubKey(@"ms-settings\Shell\Open\command", true); command.SetValue("DelegateExecute", ""); @@ -80,19 +89,21 @@ partial class WindowsPlatformServiceImpl WindowStyle = ProcessWindowStyle.Hidden, FileName = targetName, }; + var processs_start_before = new HashSet( + Process.GetProcessesByName(processName).Select(x => x.Id)); var process = Process.Start(psi); process!.WaitForExit(6000); - var processName = Path.GetFileNameWithoutExtension(fileName); for (int i = 0; i < 7; i++) { - var processs = Process.GetProcessesByName(processName); - foreach (var item in processs) + var processs_start_after = Process.GetProcessesByName(processName); + foreach (var item in processs_start_after) { + if (processs_start_before.Contains(item.Id)) + continue; + if (IsProcessElevated(item)) - { return item; - } } await Task.Delay(800); @@ -128,10 +139,9 @@ partial class WindowsPlatformServiceImpl /// /// /// - public async ValueTask StartAsAdministrator(string fileName, string? arguments = null) + internal static async ValueTask StartAsAdministrator(string fileName, string? arguments = null) { - IPlatformService thiz = this; - if (thiz.IsAdministrator) + if (IPlatformService._IsAdministrator.Value) return Process2.Start(fileName, arguments); var process = await StartAsAdministratorByBypassUAC(fileName, arguments); diff --git a/src/BD.WTTS.Client/Services.Implementation/Platform/Windows/WindowsPlatformServiceImpl.SystemOnOff.cs b/src/BD.WTTS.Client/Services.Implementation/Platform/Windows/WindowsPlatformServiceImpl.SystemOnOff.cs index 25bbef5c1..c02002d6e 100644 --- a/src/BD.WTTS.Client/Services.Implementation/Platform/Windows/WindowsPlatformServiceImpl.SystemOnOff.cs +++ b/src/BD.WTTS.Client/Services.Implementation/Platform/Windows/WindowsPlatformServiceImpl.SystemOnOff.cs @@ -51,7 +51,7 @@ partial class WindowsPlatformServiceImpl { var scheduledTaskService = IScheduledTaskService.Instance; scheduledTaskService.ThrowIsNull(); - scheduledTaskService.SetBootAutoStart(this, isAutoStart, name); + scheduledTaskService.SetBootAutoStart(isAutoStart, name); } } } diff --git a/src/BD.WTTS.Client/Services.Implementation/Platform/Windows/WindowsPlatformServiceImpl.cs b/src/BD.WTTS.Client/Services.Implementation/Platform/Windows/WindowsPlatformServiceImpl.cs index eb614a608..35f75da9c 100644 --- a/src/BD.WTTS.Client/Services.Implementation/Platform/Windows/WindowsPlatformServiceImpl.cs +++ b/src/BD.WTTS.Client/Services.Implementation/Platform/Windows/WindowsPlatformServiceImpl.cs @@ -122,8 +122,7 @@ sealed partial class WindowsPlatformServiceImpl : IPlatformService public Process? StartAsInvoker(string fileName, string? arguments = null) { - IPlatformService thiz = this; - if (thiz.IsAdministrator) + if (IPlatformService._IsAdministrator.Value) { // runas /trustlevel:0x20000 没有真正的降权,只是作为具有限制特权,使用 explorer 最好,但不接受参数,可以创建一个临时cmd脚本启动 //return StartAsInvokerByRunas(fileName, arguments); diff --git a/src/BD.WTTS.Client/Services/Platform/IPlatformService.IsAdministrator.cs b/src/BD.WTTS.Client/Services/Platform/IPlatformService.IsAdministrator.cs index 01d247668..2cdc3ca22 100644 --- a/src/BD.WTTS.Client/Services/Platform/IPlatformService.IsAdministrator.cs +++ b/src/BD.WTTS.Client/Services/Platform/IPlatformService.IsAdministrator.cs @@ -3,21 +3,21 @@ namespace BD.WTTS.Services; partial interface IPlatformService { + internal static readonly Lazy _IsAdministrator = new(() => + { +#if WINDOWS + using WindowsIdentity identity = WindowsIdentity.GetCurrent(); + return identity.IsSystem || new WindowsPrincipal(identity) + .IsInRole(WindowsBuiltInRole.Administrator); +#elif MACCATALYST || MACOS || LINUX || IOS || ANDROID + return Interop.Libc.GetEUID() == 0; +#else + throw new PlatformNotSupportedException(); +#endif + }); + /// /// 当前程序是否以 Administrator/System(Windows) 或 Root(FreeBSD/Linux/MacOS/Android/iOS) 权限运行 /// - bool IsAdministrator - { - get - { -#if WINDOWS - using WindowsIdentity identity = WindowsIdentity.GetCurrent(); - return identity.IsSystem || new WindowsPrincipal(identity) - .IsInRole(WindowsBuiltInRole.Administrator); -#elif MACCATALYST || MACOS || LINUX || IOS || ANDROID - return Interop.Libc.GetEUID() == 0; - throw new PlatformNotSupportedException(); -#endif - } - } + bool IsAdministrator => _IsAdministrator.Value; } \ No newline at end of file diff --git a/src/BD.WTTS.Client/Services/Platform/Windows/IScheduledTaskService.cs b/src/BD.WTTS.Client/Services/Platform/Windows/IScheduledTaskService.cs index 6bbf24fb8..f0df6d0d7 100644 --- a/src/BD.WTTS.Client/Services/Platform/Windows/IScheduledTaskService.cs +++ b/src/BD.WTTS.Client/Services/Platform/Windows/IScheduledTaskService.cs @@ -12,9 +12,8 @@ public interface IScheduledTaskService /// /// 开机启动使用 taskschd.msc 实现 /// - /// /// /// - void SetBootAutoStart(IPlatformService platformService, bool isAutoStart, string name); + void SetBootAutoStart(bool isAutoStart, string name); } #endif \ No newline at end of file diff --git a/src/BD.WTTS.Client/Startup/Startup.Commands.cs b/src/BD.WTTS.Client/Startup/Startup.Commands.cs index a4eb6aa77..bf79bd445 100644 --- a/src/BD.WTTS.Client/Startup/Startup.Commands.cs +++ b/src/BD.WTTS.Client/Startup/Startup.Commands.cs @@ -303,6 +303,13 @@ partial class Startup // 自定义控制台命令参数 { Handler = CommandHandler.Create(async (string n, string p) => { + if (string.IsNullOrWhiteSpace(n) || + string.IsNullOrWhiteSpace(p)) + return 400; + + if (!IPlatformService._IsAdministrator.Value) + return 401; + RunUIApplication(AppServicesLevel.IPCRoot | AppServicesLevel.Hosts); await WaitConfiguredServices; @@ -329,14 +336,35 @@ partial class Startup // 自定义控制台命令参数 rootCommand.AddCommand(sudo); #endif - // -clt plugins {插件名} {插件需要解析的参数} + // -clt plugins -l {AppServicesLevel} -m {插件名} -n {PipeName} -p {ProcessId} -a {插件需要解析的参数} var plugins = new Command("plugins", "插件使用的 IPC 服务进程") { - Handler = CommandHandler.Create(() => + Handler = CommandHandler.Create(async (uint l, string m, string n, string p, string a) => { - // TODO + if (string.IsNullOrWhiteSpace(n) || + string.IsNullOrWhiteSpace(p)) + return (int)CommandExitCode.HttpStatusBadRequest; + + var level = (AppServicesLevel)l; + RunUIApplication(level, loadModules: m); + await WaitConfiguredServices; + + if (!TryGetPlugins(out var plugins)) + return (int)CommandExitCode.GetPluginsFail; + + var plugin = plugins.FirstOrDefault(x => x.Name == m); + if (plugin == null) + return (int)CommandExitCode.GetPluginFail; + + var exitCode = await plugin.RunSubProcessMainAsync(m, n, p, a); + return exitCode; }), }; + plugins.AddOption(new Option("-l", "AppServicesLevel")); + plugins.AddOption(new Option("-m", "需要加载的模块名称")); + plugins.AddOption(new Option("-a", "需要解析的参数,使用 HttpUtility.UrlDecode 解码")); + plugins.AddOption(new Option(IPlatformService.IPCRoot.args_PipeName, "IPC 管道名")); + plugins.AddOption(new Option(IPlatformService.IPCRoot.args_ProcessId, "主进程 Id")); rootCommand.AddCommand(plugins); // -clt types @@ -345,8 +373,16 @@ partial class Startup // 自定义控制台命令参数 Handler = CommandHandler.Create(() => { int exitCode = default; - using var assemblies_stream = new FileStream(Path.Combine(IOPath.CacheDirectory, "assemblies.txt"), FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite | FileShare.Delete); - using var types_stream = new FileStream(Path.Combine(IOPath.CacheDirectory, "types.txt"), FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite | FileShare.Delete); + using var assemblies_stream = new FileStream(Path.Combine( + IOPath.CacheDirectory, "assemblies.txt"), + FileMode.OpenOrCreate, + FileAccess.Write, + FileShare.ReadWrite | FileShare.Delete); + using var types_stream = new FileStream(Path.Combine( + IOPath.CacheDirectory, "types.txt"), + FileMode.OpenOrCreate, + FileAccess.Write, + FileShare.ReadWrite | FileShare.Delete); try { var assemblies_ = AppDomain.CurrentDomain.GetAssemblies(); @@ -386,12 +422,12 @@ partial class Startup // 自定义控制台命令参数 } } } - return exitCode = 200; + return exitCode = (int)CommandExitCode.HttpStatusCodeOk; } catch (Exception ex) { Console.WriteLine(ex); - return exitCode = 500; + return exitCode = (int)CommandExitCode.HttpStatusCodeInternalServerError; } finally { @@ -410,5 +446,60 @@ partial class Startup // 自定义控制台命令参数 }; rootCommand.AddCommand(types); } + + public enum CommandExitCode + { + #region 100 ~ 5xx HttpStatusCode + + /// + HttpStatusCodeOk = 200, + + /// + HttpStatusBadRequest = 400, + + /// + HttpStatusCodeInternalServerError = 500, + + #endregion + + #region xxxx 4 位数通用错误码 + + /// + /// 参数不能为空数组 + /// + EmptyArrayArgs = 4001, + + /// + /// IPC 管道名称不能为空 + /// + EmptyPipeName = 4002, + + /// + /// 主进程 Id 不能为空 + /// + EmptyMainProcessId = 4003, + + /// + /// 主进程 Id 找不到 + /// + NotFoundMainProcessId = 4004, + + /// + /// 获取一组插件失败 + /// + GetPluginsFail = 4040, + + /// + /// 获取单个插件失败 + /// + GetPluginFail = 4041, + + /// + /// 获取子进程启动配置失败 + /// + GetSubProcessBootConfigurationFail = 4042, + + #endregion + } } #endif \ No newline at end of file diff --git a/src/BD.WTTS.Client/Startup/Startup.Host.cs b/src/BD.WTTS.Client/Startup/Startup.Host.cs index 093c670ab..cc2afad79 100644 --- a/src/BD.WTTS.Client/Startup/Startup.Host.cs +++ b/src/BD.WTTS.Client/Startup/Startup.Host.cs @@ -6,7 +6,10 @@ namespace BD.WTTS; partial class Startup // 配置 Host { [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected void RunUIApplication(AppServicesLevel? level = null, Func? sendMessage = null) + protected void RunUIApplication( + AppServicesLevel? level = null, + Func? sendMessage = null, + params string[] loadModules) { #if STARTUP_WATCH_TRACE || DEBUG WatchTrace.Start(); @@ -28,7 +31,7 @@ partial class Startup // 配置 Host #if (WINDOWS || MACCATALYST || MACOS || LINUX) && !(IOS || ANDROID) if (IsMainProcess) { - plugins = PluginsCore.InitPlugins(); + plugins = PluginsCore.InitPlugins(loadModules); HasPlugins = plugins.Any_Nullable(); #if STARTUP_WATCH_TRACE || DEBUG WatchTrace.Record("InitPlugins"); From 01d35cecbdcbbf5c81f50c84c84bceb29a17b671 Mon Sep 17 00:00:00 2001 From: Aigio Liu Date: Mon, 29 May 2023 14:09:05 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=F0=9F=90=9B=20fix=20build?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/Platform/IPlatformService.IsAdministrator.cs | 4 ++-- src/BD.WTTS.Client/Startup/Startup.Commands.cs | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/BD.WTTS.Client/Services/Platform/IPlatformService.IsAdministrator.cs b/src/BD.WTTS.Client/Services/Platform/IPlatformService.IsAdministrator.cs index 2cdc3ca22..19234cfc2 100644 --- a/src/BD.WTTS.Client/Services/Platform/IPlatformService.IsAdministrator.cs +++ b/src/BD.WTTS.Client/Services/Platform/IPlatformService.IsAdministrator.cs @@ -10,9 +10,9 @@ partial interface IPlatformService return identity.IsSystem || new WindowsPrincipal(identity) .IsInRole(WindowsBuiltInRole.Administrator); #elif MACCATALYST || MACOS || LINUX || IOS || ANDROID - return Interop.Libc.GetEUID() == 0; + return Interop.Libc.GetEUID() == 0; #else - throw new PlatformNotSupportedException(); + throw new PlatformNotSupportedException(); #endif }); diff --git a/src/BD.WTTS.Client/Startup/Startup.Commands.cs b/src/BD.WTTS.Client/Startup/Startup.Commands.cs index bf79bd445..218c04ba4 100644 --- a/src/BD.WTTS.Client/Startup/Startup.Commands.cs +++ b/src/BD.WTTS.Client/Startup/Startup.Commands.cs @@ -2,12 +2,14 @@ using dotnetCampus.Ipc.CompilerServices.GeneratedProxies; using System.CommandLine; using System.CommandLine.NamingConventionBinder; +#endif // ReSharper disable once CheckNamespace namespace BD.WTTS; partial class Startup // 自定义控制台命令参数 { +#if (WINDOWS || MACCATALYST || MACOS || LINUX) && !(IOS || ANDROID) [MethodImpl(MethodImplOptions.AggressiveInlining)] void ConfigureCommands(RootCommand rootCommand) { @@ -446,6 +448,7 @@ partial class Startup // 自定义控制台命令参数 }; rootCommand.AddCommand(types); } +#endif public enum CommandExitCode { @@ -501,5 +504,4 @@ partial class Startup // 自定义控制台命令参数 #endregion } -} -#endif \ No newline at end of file +} \ No newline at end of file From 2201ceaecf53fb43e38bbaacfe96efe660914fff Mon Sep 17 00:00:00 2001 From: RMBGAME Date: Mon, 29 May 2023 22:13:42 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20SteamClient=201.23.105?= =?UTF-8?q?29.11829?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ref/DirectoryPackages | 2 +- .../Services.Implementation/Steam/SteamServiceImpl2.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ref/DirectoryPackages b/ref/DirectoryPackages index bf939f930..075ceeacd 160000 --- a/ref/DirectoryPackages +++ b/ref/DirectoryPackages @@ -1 +1 @@ -Subproject commit bf939f9309c2bea71eaa5327857a2f5855a57f1d +Subproject commit 075ceeacd419a277a7d022a087c2030fbe69f68b diff --git a/src/BD.WTTS.Client/Services.Implementation/Steam/SteamServiceImpl2.cs b/src/BD.WTTS.Client/Services.Implementation/Steam/SteamServiceImpl2.cs index 255a73985..7d4bb1491 100644 --- a/src/BD.WTTS.Client/Services.Implementation/Steam/SteamServiceImpl2.cs +++ b/src/BD.WTTS.Client/Services.Implementation/Steam/SteamServiceImpl2.cs @@ -42,7 +42,7 @@ sealed class SteamServiceImpl2 : SteamServiceBaseImpl, ISteamConnectService protected override Dictionary? HideGameList => serviceProvider.GetService()?.HideGameList; - //protected override string? GetString(string name) => AppResources.ResourceManager.GetString(name); + protected override string? GetString(string name) => AppResources.ResourceManager.GetString(name); protected override Process? StartAsInvoker(string fileName, string? arguments = null) { From 9f836311c9335d56619da23d917bea72cbc153c6 Mon Sep 17 00:00:00 2001 From: Aigio Liu Date: Tue, 30 May 2023 14:35:00 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E2=9C=A8=20=E5=AE=A2=E6=88=B7=E7=AB=AF=20v?= =?UTF-8?q?3=20sdk=20=E6=94=B9=E5=8F=82=E6=95=B0=20localhost=EF=BC=8C?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E8=B5=B0=E6=B5=8B=E8=AF=95=E7=8E=AF=E5=A2=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BD.WTTS.Client/Models/AppSettings.cs | 9 +++++++-- src/BD.WTTS.Client/Startup/Startup.Commands.cs | 6 +++++- src/BD.WTTS.Client/Startup/Startup.OnStartup.cs | 4 ++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/BD.WTTS.Client/Models/AppSettings.cs b/src/BD.WTTS.Client/Models/AppSettings.cs index d572badf2..42c230808 100644 --- a/src/BD.WTTS.Client/Models/AppSettings.cs +++ b/src/BD.WTTS.Client/Models/AppSettings.cs @@ -123,6 +123,10 @@ public sealed partial class AppSettings : IMicroServiceClient.ISettings public static AppSettings Instance { get; } = GetAppSettings(); +#if DEBUG + internal static bool UseLocalhostApiBaseUrl { get; set; } +#endif + static AppSettings GetAppSettings() { var s = new AppSettings() @@ -136,8 +140,9 @@ public sealed partial class AppSettings : IMicroServiceClient.ISettings #endif }; #if DEBUG - s.ApiBaseUrl = Constants.Urls.BaseUrl_API_Debug; - //s.ApiBaseUrl = Constants.Urls.BaseUrl_API_Development; + s.ApiBaseUrl = UseLocalhostApiBaseUrl ? + Constants.Urls.BaseUrl_API_Debug : + Constants.Urls.BaseUrl_API_Development; #else s.ApiBaseUrl = Constants.Urls.BaseUrl_API_Production; #endif diff --git a/src/BD.WTTS.Client/Startup/Startup.Commands.cs b/src/BD.WTTS.Client/Startup/Startup.Commands.cs index 218c04ba4..551dbc62c 100644 --- a/src/BD.WTTS.Client/Startup/Startup.Commands.cs +++ b/src/BD.WTTS.Client/Startup/Startup.Commands.cs @@ -46,8 +46,12 @@ partial class Startup // 自定义控制台命令参数 var devtools = new Command("devtools"); devtools.AddOption(new Option("-disable_gpu", () => false, "禁用 GPU 硬件加速")); devtools.AddOption(new Option("-use_wgl", () => false, "使用 Native OpenGL(仅 Windows)")); - devtools.Handler = CommandHandler.Create((bool disable_gpu, bool use_wgl) => + devtools.AddOption(new Option("-use_localhost", () => false, "使用本机服务端")); + devtools.Handler = CommandHandler.Create((bool disable_gpu, bool use_wgl, bool use_localhost) => { +#if DEBUG + AppSettings.UseLocalhostApiBaseUrl = use_localhost; +#endif IsMainProcess = true; IsConsoleLineToolProcess = false; diff --git a/src/BD.WTTS.Client/Startup/Startup.OnStartup.cs b/src/BD.WTTS.Client/Startup/Startup.OnStartup.cs index 5d6ec2b6e..98b88cc40 100644 --- a/src/BD.WTTS.Client/Startup/Startup.OnStartup.cs +++ b/src/BD.WTTS.Client/Startup/Startup.OnStartup.cs @@ -31,13 +31,13 @@ partial class Startup // OnStartup if (IsMainProcess) { - Task.Run(async () => + Task2.InBackground(async () => { await ActiveUserRecordAsync(ActiveUserAnonymousStatisticType.OnStartup); }); if (GeneralSettings.AutoCheckAppUpdate.Value) { - Task.Run(async () => + Task2.InBackground(async () => { await IApplicationUpdateService.Instance .CheckUpdateAsync(showIsExistUpdateFalse: false); From b35909ec542ca7a73577b13b69d5aa60342bccad Mon Sep 17 00:00:00 2001 From: Aigio Liu Date: Tue, 30 May 2023 14:39:34 +0800 Subject: [PATCH 5/6] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Update=20dotnetCampus.?= =?UTF-8?q?Ipc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ref/DirectoryPackages | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ref/DirectoryPackages b/ref/DirectoryPackages index 075ceeacd..3d42ed8bc 160000 --- a/ref/DirectoryPackages +++ b/ref/DirectoryPackages @@ -1 +1 @@ -Subproject commit 075ceeacd419a277a7d022a087c2030fbe69f68b +Subproject commit 3d42ed8bcb6a5fc10748b872627b8be5b7ebf38f From 708eaaaf28a8fb203b53fdd2abffac4de5be8132 Mon Sep 17 00:00:00 2001 From: Aigio Liu Date: Tue, 30 May 2023 16:32:16 +0800 Subject: [PATCH 6/6] =?UTF-8?q?=E2=9C=A8=20Ipc=20Test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BD.WTTS.Client.IPC.csproj | 11 +++- .../Services/IPCSubProcessService.cs | 9 ++- ...nt.Plugins.Accelerator.ReverseProxy.csproj | 6 ++ .../IReverseProxyConfig.GlobalListener.cs | 2 +- .../{ => Abstractions}/IReverseProxyConfig.cs | 2 +- .../Program.cs | 3 + .../Properties/ImplicitUsings.cs | 10 ---- .../HttpServer/Certificates/CertService.cs | 2 +- .../LazyReverseProxyServiceImpl.cs | 2 +- .../PacketIntercept/GitInterceptor.cs | 2 +- .../PacketIntercept/HttpInterceptor.cs | 2 +- .../PacketIntercept/HttpsInterceptor.cs | 2 +- .../PacketIntercept/SshInterceptor.cs | 2 +- .../TcpInterceptHostedService.cs | 2 +- .../IReverseProxyService.Constants.cs | 9 ++- .../Services/IReverseProxyService.cs | 2 - .../BD.WTTS.Client.Plugins.Accelerator.csproj | 3 + .../Plugins/Plugin.cs | 11 ++++ src/BD.WTTS.Client/BD.WTTS.Client.csproj | 3 + src/BD.WTTS.Client/Enums/CommandExitCode.cs | 56 +++++++++++++++++++ .../Plugins/Abstractions/PluginBase.cs | 2 +- .../IPC/IPCMainProcessServiceImpl.cs | 10 +++- .../Net/HostsFileServiceImpl.cs | 2 +- .../WindowsPlatformServiceImpl.BypassUAC.cs | 22 +++++--- .../Platform/IPC/IPCPlatformService.cs | 9 ++- .../Platform/IPlatformService.Net.Hosts.cs | 12 ++++ .../Services/Platform/IPlatformService.cs | 11 ++++ .../Startup/Startup.Commands.cs | 55 ------------------ 28 files changed, 167 insertions(+), 97 deletions(-) rename src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Models/{ => Abstractions}/IReverseProxyConfig.GlobalListener.cs (98%) rename src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Models/{ => Abstractions}/IReverseProxyConfig.cs (97%) delete mode 100644 src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Properties/ImplicitUsings.cs create mode 100644 src/BD.WTTS.Client/Enums/CommandExitCode.cs diff --git a/src/BD.WTTS.Client.IPC/BD.WTTS.Client.IPC.csproj b/src/BD.WTTS.Client.IPC/BD.WTTS.Client.IPC.csproj index c28768829..77a0b213e 100644 --- a/src/BD.WTTS.Client.IPC/BD.WTTS.Client.IPC.csproj +++ b/src/BD.WTTS.Client.IPC/BD.WTTS.Client.IPC.csproj @@ -26,9 +26,9 @@ Properties - + Services @@ -38,6 +38,9 @@ Services\UI\Widgets + + Enums + @@ -46,6 +49,10 @@ + + + + diff --git a/src/BD.WTTS.Client.IPC/Services/IPCSubProcessService.cs b/src/BD.WTTS.Client.IPC/Services/IPCSubProcessService.cs index 8f08309f6..1956ea196 100644 --- a/src/BD.WTTS.Client.IPC/Services/IPCSubProcessService.cs +++ b/src/BD.WTTS.Client.IPC/Services/IPCSubProcessService.cs @@ -1,5 +1,4 @@ using dotnetCampus.Ipc.Pipes; -using ExitCode = BD.WTTS.Startup.CommandExitCode; namespace BD.WTTS.Services; @@ -44,15 +43,15 @@ public interface IPCSubProcessService : IDisposable params string[] args) { if (args.Length < 2) - return (int)ExitCode.EmptyArrayArgs; + return (int)CommandExitCode.EmptyArrayArgs; var pipeName = args[0]; if (string.IsNullOrWhiteSpace(pipeName)) - return (int)ExitCode.EmptyPipeName; + return (int)CommandExitCode.EmptyPipeName; if (!int.TryParse(args[1], out var pid)) - return (int)ExitCode.EmptyMainProcessId; + return (int)CommandExitCode.EmptyMainProcessId; var mainProcess = Process.GetProcessById(pid); if (mainProcess == null) - return (int)ExitCode.NotFoundMainProcessId; + return (int)CommandExitCode.NotFoundMainProcessId; TaskCompletionSource tcs = new(); mainProcess.EnableRaisingEvents = true; diff --git a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy.csproj b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy.csproj index fbda3d7c0..57e8f3c8b 100644 --- a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy.csproj +++ b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy.csproj @@ -31,6 +31,12 @@ Properties + + Properties + + + Properties + diff --git a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Models/IReverseProxyConfig.GlobalListener.cs b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Models/Abstractions/IReverseProxyConfig.GlobalListener.cs similarity index 98% rename from src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Models/IReverseProxyConfig.GlobalListener.cs rename to src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Models/Abstractions/IReverseProxyConfig.GlobalListener.cs index 3158752ff..3e33d70c1 100644 --- a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Models/IReverseProxyConfig.GlobalListener.cs +++ b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Models/Abstractions/IReverseProxyConfig.GlobalListener.cs @@ -4,7 +4,7 @@ using System.Net.NetworkInformation; // ReSharper disable once CheckNamespace -namespace BD.WTTS.Models; +namespace BD.WTTS.Models.Abstractions; partial interface IReverseProxyConfig { diff --git a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Models/IReverseProxyConfig.cs b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Models/Abstractions/IReverseProxyConfig.cs similarity index 97% rename from src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Models/IReverseProxyConfig.cs rename to src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Models/Abstractions/IReverseProxyConfig.cs index fbdc7008e..84c6d5ea9 100644 --- a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Models/IReverseProxyConfig.cs +++ b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Models/Abstractions/IReverseProxyConfig.cs @@ -2,7 +2,7 @@ // https://github.com/dotnetcore/FastGithub/blob/2.1.4/FastGithub.Configuration/FastGithubConfig.cs // ReSharper disable once CheckNamespace -namespace BD.WTTS.Models; +namespace BD.WTTS.Models.Abstractions; public partial interface IReverseProxyConfig { diff --git a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Program.cs b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Program.cs index 306b994b0..11914259e 100644 --- a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Program.cs +++ b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Program.cs @@ -3,6 +3,9 @@ using IHttpClientFactory_Common = System.Net.Http.Client.IHttpClientFactory; using IHttpClientFactory_Extensions_Http = System.Net.Http.IHttpClientFactory; const string moduleName = "Accelerator"; +#if DEBUG +Console.WriteLine($"This: {moduleName} / Program.Start"); +#endif try { var exitCode = await IPCSubProcessService.MainAsync(moduleName, ConfigureServices, static ipcProvider => diff --git a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Properties/ImplicitUsings.cs b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Properties/ImplicitUsings.cs deleted file mode 100644 index 2604111bd..000000000 --- a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Properties/ImplicitUsings.cs +++ /dev/null @@ -1,10 +0,0 @@ -// C# 10 定义全局 using - -#pragma warning disable IDE0079 // 请删除不必要的忽略 -#pragma warning disable IDE0005 -#pragma warning disable SA1209 // Using alias directives should be placed after other using directives -#pragma warning disable SA1211 // Using alias directives should be ordered alphabetically by alias name - -global using BD.WTTS.Enums; - -global using BD.WTTS.Models; \ No newline at end of file diff --git a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/HttpServer/Certificates/CertService.cs b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/HttpServer/Certificates/CertService.cs index 17899253c..a63fd8f3b 100644 --- a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/HttpServer/Certificates/CertService.cs +++ b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/HttpServer/Certificates/CertService.cs @@ -13,7 +13,7 @@ sealed class CertService readonly ILogger logger; readonly IReverseProxyConfig reverseProxyConfig; - IReverseProxyService ReverseProxyService => reverseProxyConfig.Service; + ReverseProxyServiceImpl ReverseProxyService => reverseProxyConfig.Service; /// /// 获取 CER 证书文件路径 diff --git a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/LazyReverseProxyServiceImpl.cs b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/LazyReverseProxyServiceImpl.cs index 172159f0f..60df75a22 100644 --- a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/LazyReverseProxyServiceImpl.cs +++ b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/LazyReverseProxyServiceImpl.cs @@ -9,7 +9,7 @@ sealed class LazyReverseProxyServiceImpl : IReverseProxyService static IReverseProxyService instance() => Ioc.Get(); #pragma warning restore IDE1006 // 命名样式 - public ICertificateManager CertificateManager => instance().CertificateManager; + //public ICertificateManager CertificateManager => instance().CertificateManager; public bool ProxyRunning => instance().ProxyRunning; diff --git a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/PacketIntercept/GitInterceptor.cs b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/PacketIntercept/GitInterceptor.cs index 9103fd5ed..517ef9a06 100644 --- a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/PacketIntercept/GitInterceptor.cs +++ b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/PacketIntercept/GitInterceptor.cs @@ -2,7 +2,7 @@ #if WINDOWS -using static BD.WTTS.Models.IReverseProxyConfig; +using static BD.WTTS.Models.Abstractions.IReverseProxyConfig; // ReSharper disable once CheckNamespace namespace BD.WTTS.Services.Implementation; diff --git a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/PacketIntercept/HttpInterceptor.cs b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/PacketIntercept/HttpInterceptor.cs index e34e2eb95..3d3871a91 100644 --- a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/PacketIntercept/HttpInterceptor.cs +++ b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/PacketIntercept/HttpInterceptor.cs @@ -2,7 +2,7 @@ #if WINDOWS -using static BD.WTTS.Models.IReverseProxyConfig; +using static BD.WTTS.Models.Abstractions.IReverseProxyConfig; // ReSharper disable once CheckNamespace namespace BD.WTTS.Services.Implementation; diff --git a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/PacketIntercept/HttpsInterceptor.cs b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/PacketIntercept/HttpsInterceptor.cs index 9725eb8eb..717dbb8bf 100644 --- a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/PacketIntercept/HttpsInterceptor.cs +++ b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/PacketIntercept/HttpsInterceptor.cs @@ -2,7 +2,7 @@ #if WINDOWS -using static BD.WTTS.Models.IReverseProxyConfig; +using static BD.WTTS.Models.Abstractions.IReverseProxyConfig; // ReSharper disable once CheckNamespace namespace BD.WTTS.Services.Implementation; diff --git a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/PacketIntercept/SshInterceptor.cs b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/PacketIntercept/SshInterceptor.cs index 2c6df84d2..253a85bd4 100644 --- a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/PacketIntercept/SshInterceptor.cs +++ b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/PacketIntercept/SshInterceptor.cs @@ -2,7 +2,7 @@ #if WINDOWS -using static BD.WTTS.Models.IReverseProxyConfig; +using static BD.WTTS.Models.Abstractions.IReverseProxyConfig; // ReSharper disable once CheckNamespace namespace BD.WTTS.Services.Implementation; diff --git a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/PacketIntercept/TcpInterceptHostedService.cs b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/PacketIntercept/TcpInterceptHostedService.cs index 9fa7e8cb9..13844a5f1 100644 --- a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/PacketIntercept/TcpInterceptHostedService.cs +++ b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/PacketIntercept/TcpInterceptHostedService.cs @@ -2,7 +2,7 @@ #if WINDOWS -using static BD.WTTS.Models.IReverseProxyConfig; +using static BD.WTTS.Models.Abstractions.IReverseProxyConfig; // ReSharper disable once CheckNamespace namespace BD.WTTS.Services.Implementation; diff --git a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services/IReverseProxyService.Constants.cs b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services/IReverseProxyService.Constants.cs index 21a84ef14..10dced25c 100644 --- a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services/IReverseProxyService.Constants.cs +++ b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services/IReverseProxyService.Constants.cs @@ -6,7 +6,7 @@ namespace BD.WTTS.Services; /// /// 反向代理服务 /// -[IpcPublic(Timeout = 55000, IgnoresIpcException = false)] +[IpcPublic(Timeout = 9000, IgnoresIpcException = false)] public partial interface IReverseProxyService : IDisposable, IReverseProxySettings { /// @@ -52,6 +52,13 @@ public partial interface IReverseProxyService : IDisposable, IReverseProxySettin /// /// ValueTask StopProxyAsync(); + +#if DEBUG + string GetDebugString() + { + return $"Pid: {Environment.ProcessId}, Exe: {Environment.ProcessPath}, Asm: {Assembly.GetAssembly(GetType())?.FullName}"; + } +#endif } /// diff --git a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services/IReverseProxyService.cs b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services/IReverseProxyService.cs index 9d96a64ab..6c136638f 100644 --- a/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services/IReverseProxyService.cs +++ b/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services/IReverseProxyService.cs @@ -3,8 +3,6 @@ namespace BD.WTTS.Services; partial interface IReverseProxyService { - ICertificateManager CertificateManager { get; } - /// /// 将 PEM 证书公钥写入 GOG GALAXY /// diff --git a/src/BD.WTTS.Client.Plugins.Accelerator/BD.WTTS.Client.Plugins.Accelerator.csproj b/src/BD.WTTS.Client.Plugins.Accelerator/BD.WTTS.Client.Plugins.Accelerator.csproj index 83a0b87fc..3f6cb089f 100644 --- a/src/BD.WTTS.Client.Plugins.Accelerator/BD.WTTS.Client.Plugins.Accelerator.csproj +++ b/src/BD.WTTS.Client.Plugins.Accelerator/BD.WTTS.Client.Plugins.Accelerator.csproj @@ -71,6 +71,9 @@ Services + + Services + Enums diff --git a/src/BD.WTTS.Client.Plugins.Accelerator/Plugins/Plugin.cs b/src/BD.WTTS.Client.Plugins.Accelerator/Plugins/Plugin.cs index 26f6e82d8..8e1891959 100644 --- a/src/BD.WTTS.Client.Plugins.Accelerator/Plugins/Plugin.cs +++ b/src/BD.WTTS.Client.Plugins.Accelerator/Plugins/Plugin.cs @@ -70,6 +70,17 @@ sealed class Plugin : PluginBase // 从子进程中获取 IPC 远程服务 reverseProxyService = await ipc.GetServiceAsync(moduleName); +#if DEBUG + try + { + var debugStringIPC = $"Pid: {Environment.ProcessId}, Exe: {Environment.ProcessPath}, Asm: {Assembly.GetAssembly(GetType())?.FullName}{Environment.NewLine}{reverseProxyService?.GetDebugString()}"; + Console.WriteLine($"DebugString/IReverseProxyService: {debugStringIPC}"); + } + catch (Exception ex) + { + Console.WriteLine(ex); + } +#endif if (ResourceService.IsChineseSimplified) { diff --git a/src/BD.WTTS.Client/BD.WTTS.Client.csproj b/src/BD.WTTS.Client/BD.WTTS.Client.csproj index e5112e8c5..1de8d76f5 100644 --- a/src/BD.WTTS.Client/BD.WTTS.Client.csproj +++ b/src/BD.WTTS.Client/BD.WTTS.Client.csproj @@ -34,6 +34,9 @@ Properties + + Properties + Properties diff --git a/src/BD.WTTS.Client/Enums/CommandExitCode.cs b/src/BD.WTTS.Client/Enums/CommandExitCode.cs new file mode 100644 index 000000000..4711785b9 --- /dev/null +++ b/src/BD.WTTS.Client/Enums/CommandExitCode.cs @@ -0,0 +1,56 @@ +namespace BD.WTTS.Enums; + +public enum CommandExitCode +{ + #region 100 ~ 5xx HttpStatusCode + + /// + HttpStatusCodeOk = 200, + + /// + HttpStatusBadRequest = 400, + + /// + HttpStatusCodeInternalServerError = 500, + + #endregion + + #region xxxx 4 位数通用错误码 + + /// + /// 参数不能为空数组 + /// + EmptyArrayArgs = 4001, + + /// + /// IPC 管道名称不能为空 + /// + EmptyPipeName = 4002, + + /// + /// 主进程 Id 不能为空 + /// + EmptyMainProcessId = 4003, + + /// + /// 主进程 Id 找不到 + /// + NotFoundMainProcessId = 4004, + + /// + /// 获取一组插件失败 + /// + GetPluginsFail = 4040, + + /// + /// 获取单个插件失败 + /// + GetPluginFail = 4041, + + /// + /// 获取子进程启动配置失败 + /// + GetSubProcessBootConfigurationFail = 4042, + + #endregion +} \ No newline at end of file diff --git a/src/BD.WTTS.Client/Plugins/Abstractions/PluginBase.cs b/src/BD.WTTS.Client/Plugins/Abstractions/PluginBase.cs index 36d293256..1f4c8ac0d 100644 --- a/src/BD.WTTS.Client/Plugins/Abstractions/PluginBase.cs +++ b/src/BD.WTTS.Client/Plugins/Abstractions/PluginBase.cs @@ -93,7 +93,7 @@ public abstract class PluginBase : IPlugin where TPlugin : PluginBase { - var process = await WindowsPlatformServiceImpl.StartAsAdministrator(processPath, arguments); - return process; + return await Policy.HandleResult(x => x == null) + .RetryAsync(3) + .ExecuteAsync(async () => + { + var process = await WindowsPlatformServiceImpl.StartAsAdministrator(processPath, arguments); + return process; + }); }); await IPlatformService.IPCRoot.SetIPC(this); }); diff --git a/src/BD.WTTS.Client/Services.Implementation/Net/HostsFileServiceImpl.cs b/src/BD.WTTS.Client/Services.Implementation/Net/HostsFileServiceImpl.cs index 893829e62..89d4bd709 100644 --- a/src/BD.WTTS.Client/Services.Implementation/Net/HostsFileServiceImpl.cs +++ b/src/BD.WTTS.Client/Services.Implementation/Net/HostsFileServiceImpl.cs @@ -497,7 +497,7 @@ internal sealed class HostsFileServiceImpl { try { - s.WriteDefaultHostsContent(new FileStream(s.HostsFilePath, FileMode.OpenOrCreate)); + s.WriteDefaultHostsContent(); Toast.Show(AppResources.CommunityFix_ResetHostsFileOk); } catch (Exception e) diff --git a/src/BD.WTTS.Client/Services.Implementation/Platform/Windows/WindowsPlatformServiceImpl.BypassUAC.cs b/src/BD.WTTS.Client/Services.Implementation/Platform/Windows/WindowsPlatformServiceImpl.BypassUAC.cs index e2175f46e..403712cdf 100644 --- a/src/BD.WTTS.Client/Services.Implementation/Platform/Windows/WindowsPlatformServiceImpl.BypassUAC.cs +++ b/src/BD.WTTS.Client/Services.Implementation/Platform/Windows/WindowsPlatformServiceImpl.BypassUAC.cs @@ -148,14 +148,22 @@ partial class WindowsPlatformServiceImpl if (process != null) return process; - ProcessStartInfo psi = new() + try { - FileName = fileName, - Arguments = arguments, - UseShellExecute = true, - Verb = "runas", - }; - return Process.Start(psi); + ProcessStartInfo psi = new() + { + FileName = fileName, + Arguments = arguments, + UseShellExecute = true, + Verb = "runas", + }; + var process_runas = Process.Start(psi); + return process_runas; + } + catch + { + return null; + } } } #endif \ No newline at end of file diff --git a/src/BD.WTTS.Client/Services/Platform/IPC/IPCPlatformService.cs b/src/BD.WTTS.Client/Services/Platform/IPC/IPCPlatformService.cs index 61afde338..59da0f251 100644 --- a/src/BD.WTTS.Client/Services/Platform/IPC/IPCPlatformService.cs +++ b/src/BD.WTTS.Client/Services/Platform/IPC/IPCPlatformService.cs @@ -6,8 +6,13 @@ namespace BD.WTTS.Services; /// /// 用于 IPC 的平台实现的服务 /// -[IpcPublic(Timeout = 55000, IgnoresIpcException = false)] +[IpcPublic(Timeout = 9000, IgnoresIpcException = false)] public partial interface IPCPlatformService { - +#if DEBUG + string GetDebugString() + { + return $"Pid: {Environment.ProcessId}, Exe: {Environment.ProcessPath}, Asm: {Assembly.GetAssembly(GetType())?.FullName}"; + } +#endif } \ No newline at end of file diff --git a/src/BD.WTTS.Client/Services/Platform/IPlatformService.Net.Hosts.cs b/src/BD.WTTS.Client/Services/Platform/IPlatformService.Net.Hosts.cs index 731af0cbc..bcc39cc16 100644 --- a/src/BD.WTTS.Client/Services/Platform/IPlatformService.Net.Hosts.cs +++ b/src/BD.WTTS.Client/Services/Platform/IPlatformService.Net.Hosts.cs @@ -27,6 +27,18 @@ partial interface IPlatformService [Obsolete("use WriteDefaultHostsContent(Stream", true)] string DefaultHostsContent => string.Empty; + /// + /// 写入默认 hosts 文件内容 + /// + void WriteDefaultHostsContent() + { + var fileStream = new FileStream(HostsFilePath, + FileMode.OpenOrCreate, + FileAccess.Write, + FileShare.ReadWrite | FileShare.Delete); + WriteDefaultHostsContent(fileStream); + } + /// /// 写入默认 hosts 文件内容 /// diff --git a/src/BD.WTTS.Client/Services/Platform/IPlatformService.cs b/src/BD.WTTS.Client/Services/Platform/IPlatformService.cs index 472e9fcdc..637198cfd 100644 --- a/src/BD.WTTS.Client/Services/Platform/IPlatformService.cs +++ b/src/BD.WTTS.Client/Services/Platform/IPlatformService.cs @@ -33,6 +33,17 @@ public partial interface IPlatformService : IPCPlatformService { var iPCPlatformService = await ipc.GetServiceAsync(moduleName); iPCPlatformService.ThrowIsNull(); +#if DEBUG + try + { + var debugStringIPC = $"Pid: {Environment.ProcessId}, Exe: {Environment.ProcessPath}, Asm: {Assembly.GetAssembly(typeof(IPlatformService))?.FullName}{Environment.NewLine}{iPCPlatformService.GetDebugString()}"; + Console.WriteLine($"DebugString/IPCPlatformService: {debugStringIPC}"); + } + catch (Exception ex) + { + Console.WriteLine(ex); + } +#endif tcs.TrySetResult(iPCPlatformService); } catch (Exception ex) diff --git a/src/BD.WTTS.Client/Startup/Startup.Commands.cs b/src/BD.WTTS.Client/Startup/Startup.Commands.cs index 551dbc62c..a059cc0ed 100644 --- a/src/BD.WTTS.Client/Startup/Startup.Commands.cs +++ b/src/BD.WTTS.Client/Startup/Startup.Commands.cs @@ -453,59 +453,4 @@ partial class Startup // 自定义控制台命令参数 rootCommand.AddCommand(types); } #endif - - public enum CommandExitCode - { - #region 100 ~ 5xx HttpStatusCode - - /// - HttpStatusCodeOk = 200, - - /// - HttpStatusBadRequest = 400, - - /// - HttpStatusCodeInternalServerError = 500, - - #endregion - - #region xxxx 4 位数通用错误码 - - /// - /// 参数不能为空数组 - /// - EmptyArrayArgs = 4001, - - /// - /// IPC 管道名称不能为空 - /// - EmptyPipeName = 4002, - - /// - /// 主进程 Id 不能为空 - /// - EmptyMainProcessId = 4003, - - /// - /// 主进程 Id 找不到 - /// - NotFoundMainProcessId = 4004, - - /// - /// 获取一组插件失败 - /// - GetPluginsFail = 4040, - - /// - /// 获取单个插件失败 - /// - GetPluginFail = 4041, - - /// - /// 获取子进程启动配置失败 - /// - GetSubProcessBootConfigurationFail = 4042, - - #endregion - } } \ No newline at end of file