Skip to content

Commit 1cd8de8

Browse files
committed
🎨 Ipc
1 parent a9a06d1 commit 1cd8de8

File tree

3 files changed

+118
-56
lines changed

3 files changed

+118
-56
lines changed

src/BD.Common8.Bcl/Diagnostics/Process2.StartAsPrivileged.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,19 @@ partial class Process2
55
/// <summary>
66
/// 提权启动进程,如果 UAC 弹窗取消则返回 <see langword="null"/>
77
/// </summary>
8-
/// <param name="fileName"></param>
9-
/// <param name="arguments"></param>
8+
/// <param name="fileName">进程可执行文件路径</param>
9+
/// <param name="arguments">参数</param>
10+
/// <param name="forceRunas">是否强制用 runas 启动</param>
1011
/// <returns></returns>
11-
public static Process? StartAsPrivileged(string fileName, object? arguments = null)
12+
public static Process? StartAsPrivileged(
13+
string fileName,
14+
object? arguments = null,
15+
bool forceRunas = false)
1216
{
1317
Process? process;
1418
try
1519
{
16-
if (Environment.IsPrivilegedProcess)
20+
if (!forceRunas && Environment.IsPrivilegedProcess)
1721
{
1822
process = Start(fileName, arguments);
1923
}

src/BD.Common8.Ipc.Client/Services/Implementation/IpcClientService.cs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,8 @@ string GetHubUrl()
9393
oldHandler.Dispose(); // 传过来的 Handler 丢弃,使用根据连接字符串解析的
9494
if (hubConnHandler.Disposed)
9595
{
96-
#if DEBUG
97-
Console.WriteLine("已重新创建 HubConnDelegatingHandler");
98-
#endif
96+
HubConnDelegatingHandlerDebugWriteLine();
97+
Task.WaitAll(OnHttpMessageHandlerFactoryAsync());
9998
hubConnHandler = IpcAppConnectionStringHelper.GetHttpMessageHandler(connectionString);
10099
ConfigureSocketsHttpHandler(hubConnHandler.InnerHandler);
101100
}
@@ -185,6 +184,11 @@ protected virtual Task HubConnection_Reconnected(string? arg)
185184
return Task.CompletedTask;
186185
}
187186

187+
protected virtual Task OnHttpMessageHandlerFactoryAsync()
188+
{
189+
return Task.CompletedTask;
190+
}
191+
188192
/// <inheritdoc/>
189193
public async ValueTask DisposeAsync()
190194
{
@@ -217,7 +221,10 @@ protected virtual async ValueTask DisposeAsyncCore()
217221
httpClient = null;
218222
hubConnections = null!;
219223
}
224+
}
220225

226+
partial class IpcClientService // OnError
227+
{
221228
/// <summary>
222229
/// 当请求出现错误时
223230
/// </summary>
@@ -263,4 +270,23 @@ protected virtual async ValueTask DisposeAsyncCore()
263270

264271
return default;
265272
}
266-
}
273+
}
274+
275+
#if DEBUG
276+
partial class IpcClientService
277+
{
278+
const string f = """
279+
已重新创建 HubConnDelegatingHandler,如果后端进程未启动,使用管理员运行终端并输入以下命令:
280+
cd {0}
281+
{1} {2}
282+
""";
283+
284+
static void HubConnDelegatingHandlerDebugWriteLine()
285+
{
286+
Console.WriteLine(f,
287+
Path.GetDirectoryName(Environment.ProcessPath),
288+
Path.GetFileNameWithoutExtension(Environment.ProcessPath),
289+
MobiusHost.GetBackendProcessArguments());
290+
}
291+
}
292+
#endif

src/BD.Common8.Ipc.Server/Services/Implementation/IpcServerService.cs

Lines changed: 80 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,15 @@ public abstract class IpcServerService(X509Certificate2 serverCertificate) : IIp
5555
/// <returns></returns>
5656
public async ValueTask WebApplicationExit()
5757
{
58+
#if DEBUG
59+
//Console.WriteLine("后端进程退出(WebApplicationExit)等待 StopAsync 与 DisposeAsync,StackTrace:" + Environment.NewLine + Environment.StackTrace);
60+
Console.WriteLine("后端进程退出(WebApplicationExit)等待 StopAsync 与 DisposeAsync");
61+
#endif
5862
if (app != null)
5963
{
64+
await app.StopAsync();
6065
await app.DisposeAsync();
6166
}
62-
tcs_app.TrySetResult();
6367
}
6468

6569
readonly TaskCompletionSource tcs_app = new();
@@ -87,9 +91,19 @@ public async ValueTask RunAsync()
8791

8892
Task2.InBackground(() =>
8993
{
90-
app.ThrowIsNull().Run();
91-
Exited?.Invoke();
92-
tcs_app.TrySetResult();
94+
try
95+
{
96+
app.ThrowIsNull().Run();
97+
#if DEBUG
98+
Console.WriteLine("后端进程退出(Microsoft.AspNetCore.Builder.WebApplication.Run 完成)");
99+
#endif
100+
Exited?.Invoke();
101+
tcs_app.TrySetResult();
102+
}
103+
catch (Exception ex)
104+
{
105+
tcs_app.TrySetException(ex);
106+
}
93107
}, longRunning: true);
94108
}
95109

@@ -186,9 +200,9 @@ static bool IsUsePort(IPAddress address, int port)
186200
builder.Services.AddRoutingCore();
187201
builder.Services.AddLogging(ConfigureLogging);
188202
builder.Services.ConfigureHttpJsonOptions(ConfigureHttpJsonOptions);
189-
builder.Services.AddSingleton(
190-
typeof(HubConnectionHandler<>),
191-
typeof(FixHubConnectionHandler<>));
203+
//builder.Services.AddSingleton(
204+
// typeof(HubConnectionHandler<>),
205+
// typeof(FixHubConnectionHandler<>));
192206
var signalRServerBuilder = builder.Services.AddSignalR(ConfigureSignalR);
193207
ConfigureSignalRProtocol(signalRServerBuilder);
194208
builder.Services.AddHttpContextAccessor();
@@ -514,11 +528,11 @@ void DeleteUnixSocketFile()
514528
/// <inheritdoc cref="IAsyncDisposable.DisposeAsync"/>
515529
protected virtual async ValueTask DisposeAsyncCore()
516530
{
517-
//if (app is not null)
518-
//{
519-
// await app.StopAsync().ConfigureAwait(false);
520-
// await app.DisposeAsync().ConfigureAwait(false);
521-
//}
531+
if (app is not null)
532+
{
533+
await app.StopAsync().ConfigureAwait(false);
534+
await app.DisposeAsync().ConfigureAwait(false);
535+
}
522536
if (lock_RunAsync is not null)
523537
{
524538
await lock_RunAsync.DisposeAsync().ConfigureAwait(false);
@@ -542,16 +556,16 @@ protected virtual void Dispose(bool disposing)
542556
if (disposing)
543557
{
544558
// 释放托管状态(托管对象)
545-
//if (app != null)
546-
//{
547-
// app.StopAsync().GetAwaiter().GetResult();
559+
if (app != null)
560+
{
561+
app.StopAsync().GetAwaiter().GetResult();
548562

549-
// if (app is IDisposable disposable_app)
550-
// {
551-
// disposable_app.Dispose();
552-
// app = null;
553-
// }
554-
//}
563+
if (app is IDisposable disposable_app)
564+
{
565+
disposable_app.Dispose();
566+
app = null;
567+
}
568+
}
555569

556570
if (lock_RunAsync is not null)
557571
{
@@ -565,6 +579,8 @@ protected virtual void Dispose(bool disposing)
565579
serverCertificate = null!;
566580
}
567581

582+
app = null;
583+
568584
DeleteUnixSocketFile();
569585
}
570586
}
@@ -645,30 +661,46 @@ protected override Task<AuthenticateResult> HandleAuthenticateAsync()
645661
}
646662
}
647663

648-
file sealed class FixHubConnectionHandler<
649-
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] THub>(
650-
HubLifetimeManager<THub> lifetimeManager,
651-
IHubProtocolResolver protocolResolver,
652-
IOptions<HubOptions> globalHubOptions,
653-
IOptions<HubOptions<THub>> hubOptions,
654-
ILoggerFactory loggerFactory,
655-
IUserIdProvider userIdProvider,
656-
IServiceScopeFactory serviceScopeFactory) :
657-
HubConnectionHandler<THub>(lifetimeManager, protocolResolver, globalHubOptions,
658-
hubOptions, loggerFactory, userIdProvider,
659-
serviceScopeFactory)
660-
where THub : Hub
661-
{
662-
/// <inheritdoc/>
663-
public sealed override async Task OnConnectedAsync(ConnectionContext connection)
664-
{
665-
try
666-
{
667-
await base.OnConnectedAsync(connection);
668-
}
669-
catch (ObjectDisposedException)
670-
{
671-
// 应用程序退出时引发 Ioc 被释放异常忽略
672-
}
673-
}
674-
}
664+
//file sealed class FixHubConnectionHandler<
665+
// [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] THub>(
666+
// HubLifetimeManager<THub> lifetimeManager,
667+
// IHubProtocolResolver protocolResolver,
668+
// IOptions<HubOptions> globalHubOptions,
669+
// IOptions<HubOptions<THub>> hubOptions,
670+
// ILoggerFactory loggerFactory,
671+
// IUserIdProvider userIdProvider,
672+
// IServiceScopeFactory serviceScopeFactory) :
673+
// HubConnectionHandler<THub>(lifetimeManager, protocolResolver, globalHubOptions,
674+
// hubOptions, loggerFactory, userIdProvider,
675+
// serviceScopeFactory)
676+
// where THub : Hub
677+
//{
678+
// /// <inheritdoc/>
679+
// public sealed override async Task OnConnectedAsync(ConnectionContext connection)
680+
// {
681+
// using var scope = serviceScopeFactory.CreateScope();
682+
683+
// try
684+
// {
685+
// await base.OnConnectedAsync(connection);
686+
// }
687+
// catch (ObjectDisposedException)
688+
// {
689+
// var isExiting = HostConstants.IsExiting;
690+
// if (!isExiting)
691+
// {
692+
// throw;
693+
// }
694+
// // https://github.com/dotnet/aspnetcore/blob/v9.0.3/src/SignalR/server/Core/src/HubConnectionHandler.cs#L234
695+
// // fail: Microsoft.AspNetCore.SignalR.HubConnectionHandler[1]
696+
// // Error when dispatching 'OnDisconnectedAsync' on hub.
697+
// // System.ObjectDisposedException: Cannot access a disposed object.
698+
// // Object name: 'IServiceProvider'.
699+
// // at Microsoft.Extensions.DependencyInjection.ServiceLookup.ThrowHelper.ThrowObjectDisposedException()
700+
// // at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateScope()
701+
// // at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.CreateAsyncScope(IServiceScopeFactory serviceScopeFactory)
702+
// // at Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher`1.OnDisconnectedAsync(HubConnectionContext connection, Exception exception)
703+
// // at Microsoft.AspNetCore.SignalR.HubConnectionHandler`1.HubOnDisconnectedAsync(HubConnectionContext connection, Exception exception)
704+
// }
705+
// }
706+
//}

0 commit comments

Comments
 (0)