✨ Ipc Test

This commit is contained in:
Aigio Liu
2023-05-30 16:32:16 +08:00
parent b35909ec54
commit 708eaaaf28
28 changed files with 167 additions and 97 deletions
@@ -26,9 +26,9 @@
<Compile Include="..\ImplicitUsings.Nito.cs">
<LinkBase>Properties</LinkBase>
</Compile>
<!--<Compile Include="..\ImplicitUsings.Enums.cs">
<Compile Include="..\ImplicitUsings.Enums.cs">
<LinkBase>Properties</LinkBase>
</Compile>-->
</Compile>
<Compile Include="..\BD.WTTS.Client\Services\IPC\IPCSubProcessModuleService.cs">
<LinkBase>Services</LinkBase>
</Compile>
@@ -38,6 +38,9 @@
<Compile Include="..\BD.WTTS.Client\Services\UI\Widgets\IPC\*.cs">
<LinkBase>Services\UI\Widgets</LinkBase>
</Compile>
<Compile Include="..\BD.WTTS.Client\Enums\CommandExitCode.cs">
<LinkBase>Enums</LinkBase>
</Compile>
</ItemGroup>
<ItemGroup>
@@ -46,6 +49,10 @@
<PackageReference Include="dotnetCampus.Ipc" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<Import Project="..\TFM_NET7_WITH_ALL.props" />
</Project>
@@ -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;
@@ -31,6 +31,12 @@
<Compile Include="..\ImplicitUsings.Nito.cs">
<LinkBase>Properties</LinkBase>
</Compile>
<Compile Include="..\ImplicitUsings.Models.cs">
<LinkBase>Properties</LinkBase>
</Compile>
<Compile Include="..\ImplicitUsings.Enums.cs">
<LinkBase>Properties</LinkBase>
</Compile>
</ItemGroup>
<ItemGroup>
@@ -4,7 +4,7 @@
using System.Net.NetworkInformation;
// ReSharper disable once CheckNamespace
namespace BD.WTTS.Models;
namespace BD.WTTS.Models.Abstractions;
partial interface IReverseProxyConfig
{
@@ -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
{
@@ -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 =>
@@ -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;
@@ -13,7 +13,7 @@ sealed class CertService
readonly ILogger<CertService> logger;
readonly IReverseProxyConfig reverseProxyConfig;
IReverseProxyService ReverseProxyService => reverseProxyConfig.Service;
ReverseProxyServiceImpl ReverseProxyService => reverseProxyConfig.Service;
/// <summary>
/// 获取 CER 证书文件路径
@@ -9,7 +9,7 @@ sealed class LazyReverseProxyServiceImpl : IReverseProxyService
static IReverseProxyService instance() => Ioc.Get<IReverseProxyService>();
#pragma warning restore IDE1006 // 命名样式
public ICertificateManager CertificateManager => instance().CertificateManager;
//public ICertificateManager CertificateManager => instance().CertificateManager;
public bool ProxyRunning => instance().ProxyRunning;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -6,7 +6,7 @@ namespace BD.WTTS.Services;
/// <summary>
/// 反向代理服务
/// </summary>
[IpcPublic(Timeout = 55000, IgnoresIpcException = false)]
[IpcPublic(Timeout = 9000, IgnoresIpcException = false)]
public partial interface IReverseProxyService : IDisposable, IReverseProxySettings
{
/// <summary>
@@ -52,6 +52,13 @@ public partial interface IReverseProxyService : IDisposable, IReverseProxySettin
/// </summary>
/// <returns></returns>
ValueTask StopProxyAsync();
#if DEBUG
string GetDebugString()
{
return $"Pid: {Environment.ProcessId}, Exe: {Environment.ProcessPath}, Asm: {Assembly.GetAssembly(GetType())?.FullName}";
}
#endif
}
/// <summary>
@@ -3,8 +3,6 @@ namespace BD.WTTS.Services;
partial interface IReverseProxyService
{
ICertificateManager CertificateManager { get; }
/// <summary>
/// 将 PEM 证书公钥写入 GOG GALAXY
/// </summary>
@@ -71,6 +71,9 @@
<Compile Include="..\BD.WTTS.Client.Plugins.Accelerator.ReverseProxy\Services\IReverseProxyService.Constants.cs">
<LinkBase>Services</LinkBase>
</Compile>
<Compile Include="..\BD.WTTS.Client.Plugins.Accelerator.ReverseProxy\Services\IReverseProxyService.cs">
<LinkBase>Services</LinkBase>
</Compile>
<Compile Include="..\BD.WTTS.Client.Plugins.Accelerator.ReverseProxy\Enums\ExternalProxyType.cs">
<LinkBase>Enums</LinkBase>
</Compile>
@@ -70,6 +70,17 @@ sealed class Plugin : PluginBase<Plugin>
// 从子进程中获取 IPC 远程服务
reverseProxyService = await ipc.GetServiceAsync<IReverseProxyService>(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)
{
+3
View File
@@ -34,6 +34,9 @@
<Compile Include="..\ImplicitUsings.Models.cs">
<LinkBase>Properties</LinkBase>
</Compile>
<Compile Include="..\ImplicitUsings.Enums.cs">
<LinkBase>Properties</LinkBase>
</Compile>
<Compile Include="..\ImplicitUsings.UI.cs">
<LinkBase>Properties</LinkBase>
</Compile>
@@ -0,0 +1,56 @@
namespace BD.WTTS.Enums;
public enum CommandExitCode
{
#region 100 ~ 5xx HttpStatusCode
/// <inheritdoc cref="HttpStatusCode.OK"/>
HttpStatusCodeOk = 200,
/// <inheritdoc cref="HttpStatusCode.BadRequest"/>
HttpStatusBadRequest = 400,
/// <inheritdoc cref="HttpStatusCode.InternalServerError"/>
HttpStatusCodeInternalServerError = 500,
#endregion
#region xxxx 4 位数通用错误码
/// <summary>
/// 参数不能为空数组
/// </summary>
EmptyArrayArgs = 4001,
/// <summary>
/// IPC 管道名称不能为空
/// </summary>
EmptyPipeName = 4002,
/// <summary>
/// 主进程 Id 不能为空
/// </summary>
EmptyMainProcessId = 4003,
/// <summary>
/// 主进程 Id 找不到
/// </summary>
NotFoundMainProcessId = 4004,
/// <summary>
/// 获取一组插件失败
/// </summary>
GetPluginsFail = 4040,
/// <summary>
/// 获取单个插件失败
/// </summary>
GetPluginFail = 4041,
/// <summary>
/// 获取子进程启动配置失败
/// </summary>
GetSubProcessBootConfigurationFail = 4042,
#endregion
}
@@ -93,7 +93,7 @@ public abstract class PluginBase<TPlugin> : IPlugin where TPlugin : PluginBase<T
{
var subProcessBootConfiguration = GetSubProcessBootConfiguration(encodedArgs ?? string.Empty);
if (subProcessBootConfiguration == default)
return (int)Startup.CommandExitCode.GetSubProcessBootConfigurationFail;
return (int)CommandExitCode.GetSubProcessBootConfigurationFail;
var exitCode = await IPCSubProcessService.MainAsync(moduleName,
subProcessBootConfiguration.configureServices,
@@ -2,6 +2,7 @@ using dotnetCampus.Ipc.CompilerServices.GeneratedProxies;
using dotnetCampus.Ipc.Context;
using dotnetCampus.Ipc.Pipes;
using dotnetCampus.Ipc.Utils.Logging;
using Polly;
using IPCLogLevel = dotnetCampus.Ipc.Utils.Logging.LogLevel;
using MSEXLogLevel = Microsoft.Extensions.Logging.LogLevel;
@@ -188,8 +189,13 @@ public sealed partial class IPCMainProcessServiceImpl : IPCMainProcessService
var arguments = string.Format(arguments_, pipeName, pid);
await AddDaemonWithStartSubProcessAsync(IPlatformService.IPCRoot.moduleName, async _ =>
{
var process = await WindowsPlatformServiceImpl.StartAsAdministrator(processPath, arguments);
return process;
return await Policy.HandleResult<Process?>(x => x == null)
.RetryAsync(3)
.ExecuteAsync(async () =>
{
var process = await WindowsPlatformServiceImpl.StartAsAdministrator(processPath, arguments);
return process;
});
});
await IPlatformService.IPCRoot.SetIPC(this);
});
@@ -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)
@@ -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
@@ -6,8 +6,13 @@ namespace BD.WTTS.Services;
/// <summary>
/// 用于 IPC 的平台实现的服务
/// </summary>
[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
}
@@ -27,6 +27,18 @@ partial interface IPlatformService
[Obsolete("use WriteDefaultHostsContent(Stream", true)]
string DefaultHostsContent => string.Empty;
/// <summary>
/// 写入默认 hosts 文件内容
/// </summary>
void WriteDefaultHostsContent()
{
var fileStream = new FileStream(HostsFilePath,
FileMode.OpenOrCreate,
FileAccess.Write,
FileShare.ReadWrite | FileShare.Delete);
WriteDefaultHostsContent(fileStream);
}
/// <summary>
/// 写入默认 hosts 文件内容
/// </summary>
@@ -33,6 +33,17 @@ public partial interface IPlatformService : IPCPlatformService
{
var iPCPlatformService = await ipc.GetServiceAsync<IPCPlatformService>(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)
@@ -453,59 +453,4 @@ partial class Startup // 自定义控制台命令参数
rootCommand.AddCommand(types);
}
#endif
public enum CommandExitCode
{
#region 100 ~ 5xx HttpStatusCode
/// <inheritdoc cref="HttpStatusCode.OK"/>
HttpStatusCodeOk = 200,
/// <inheritdoc cref="HttpStatusCode.BadRequest"/>
HttpStatusBadRequest = 400,
/// <inheritdoc cref="HttpStatusCode.InternalServerError"/>
HttpStatusCodeInternalServerError = 500,
#endregion
#region xxxx 4 位数通用错误码
/// <summary>
/// 参数不能为空数组
/// </summary>
EmptyArrayArgs = 4001,
/// <summary>
/// IPC 管道名称不能为空
/// </summary>
EmptyPipeName = 4002,
/// <summary>
/// 主进程 Id 不能为空
/// </summary>
EmptyMainProcessId = 4003,
/// <summary>
/// 主进程 Id 找不到
/// </summary>
NotFoundMainProcessId = 4004,
/// <summary>
/// 获取一组插件失败
/// </summary>
GetPluginsFail = 4040,
/// <summary>
/// 获取单个插件失败
/// </summary>
GetPluginFail = 4041,
/// <summary>
/// 获取子进程启动配置失败
/// </summary>
GetSubProcessBootConfigurationFail = 4042,
#endregion
}
}