From 78389746aa6a6eab8788b774047e1610a5a36532 Mon Sep 17 00:00:00 2001 From: StarInk Date: Wed, 25 Feb 2026 03:46:32 +0100 Subject: [PATCH 1/5] =?UTF-8?q?=F0=9F=92=BE=20=F0=9F=8E=87=20Feat,=20Style?= =?UTF-8?q?(Loaders):=20=E5=A2=9E=E5=BC=BA=20Loader=20=E9=80=9A=E4=BF=A1?= =?UTF-8?q?=E5=92=8C=E5=8F=82=E6=95=B0=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- KitX.Loader.CSharp/ArgsParser.cs | 61 ++++++++++++++++------ KitX.Loader.CSharp/CommunicationManager.cs | 6 ++- KitX.Loader.WPF.Core/App.xaml.cs | 5 +- 3 files changed, 53 insertions(+), 19 deletions(-) diff --git a/KitX.Loader.CSharp/ArgsParser.cs b/KitX.Loader.CSharp/ArgsParser.cs index cbb2afc..a6d7f36 100644 --- a/KitX.Loader.CSharp/ArgsParser.cs +++ b/KitX.Loader.CSharp/ArgsParser.cs @@ -1,4 +1,5 @@ -using CommandLine; +using System.Threading.Tasks; +using CommandLine; namespace KitX.Loader.CSharp; @@ -9,24 +10,54 @@ public static void Parse(string[] args) Parser.Default.ParseArguments(args) .WithParsed(async option => { - if (option.PluginPath is null) - return; + await ParseOptionAsync(option); + }); + } - if (option.WorkingDirectory is not null) - Directory.SetCurrentDirectory(option.WorkingDirectory); + public static Task ParseAsync(string[] args) + { + var tcs = new TaskCompletionSource(); - var communicationManager = new CommunicationManager(); + Parser.Default.ParseArguments(args) + .WithParsed(async option => + { + try + { + await ParseOptionAsync(option); + tcs.SetResult(true); + } + catch (Exception ex) + { + tcs.SetException(ex); + } + }) + .WithNotParsed(errors => + { + tcs.SetResult(false); + }); - if (option.ConnectUrl is not null) - communicationManager = await communicationManager.Connect(option.ConnectUrl); - else communicationManager = null; + return tcs.Task; + } + + private static async Task ParseOptionAsync(Options option) + { + if (option.PluginPath is null) + return; - var pluginManager = new PluginManager() - .OnSendMessage(x => communicationManager?.SendMessageAsync(x)) - .LoadPlugin(option.PluginPath); + if (option.WorkingDirectory is not null) + Directory.SetCurrentDirectory(option.WorkingDirectory); - if (communicationManager is not null) - communicationManager.OnReceiveMessage = x => pluginManager.ReceiveMessage(x); - }); + var communicationManager = new CommunicationManager(); + + if (option.ConnectUrl is not null) + communicationManager = await communicationManager.Connect(option.ConnectUrl); + else communicationManager = null; + + var pluginManager = new PluginManager() + .OnSendMessage(x => communicationManager?.SendMessageAsync(x)) + .LoadPlugin(option.PluginPath); + + if (communicationManager is not null) + communicationManager.OnReceiveMessage = x => pluginManager.ReceiveMessage(x); } } diff --git a/KitX.Loader.CSharp/CommunicationManager.cs b/KitX.Loader.CSharp/CommunicationManager.cs index f1b8c99..7c2440d 100644 --- a/KitX.Loader.CSharp/CommunicationManager.cs +++ b/KitX.Loader.CSharp/CommunicationManager.cs @@ -27,8 +27,9 @@ public async Task Connect(string? url) await Client.ConnectAsync(new Uri(url), CancellationToken.None); var waiting = true; + var timeout = DateTime.Now.AddSeconds(30); // 30 second timeout - while (waiting) + while (waiting && DateTime.Now < timeout) { switch (Client.State) { @@ -36,9 +37,10 @@ public async Task Connect(string? url) waiting = false; break; case WebSocketState.Connecting: + await Task.Delay(10); // Wait a bit before checking again break; case WebSocketState.Open: - new Thread(async () => await ReceiveAsync()).Start(); + _ = ReceiveAsync(); // Start receiving in background waiting = false; break; case WebSocketState.CloseSent: diff --git a/KitX.Loader.WPF.Core/App.xaml.cs b/KitX.Loader.WPF.Core/App.xaml.cs index 93fb183..3248a71 100644 --- a/KitX.Loader.WPF.Core/App.xaml.cs +++ b/KitX.Loader.WPF.Core/App.xaml.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; using System.Windows; using KitX.Loader.CSharp; @@ -6,11 +7,11 @@ namespace KitX.Loader.WPF.Core; public partial class App : Application { - private void Application_Startup(object sender, StartupEventArgs e) + private async void Application_Startup(object sender, StartupEventArgs e) { try { - ArgsParser.Parse(e.Args); + await ArgsParser.ParseAsync(e.Args); } catch (Exception o) { From ea462cbc61113c6c5098169d0515387b90d48329 Mon Sep 17 00:00:00 2001 From: StarInk Date: Sun, 15 Mar 2026 05:07:49 +0100 Subject: [PATCH 2/5] =?UTF-8?q?=F0=9F=94=A7=20Fix(KitX.Loader.CSharp):=20A?= =?UTF-8?q?dd=20some=20debug=20output;=20Make=20it=20possible=20to=20keep?= =?UTF-8?q?=20the=20console=20plugins=20live.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- KitX.Loader.CSharp/ArgsParser.cs | 47 +++++++++++++++-- KitX.Loader.CSharp/CommunicationManager.cs | 40 ++++++++++++++- KitX.Loader.CSharp/PluginManager.cs | 60 +++++++++++++++++++++- KitX.Loader.CSharp/Program.cs | 18 ++++++- 4 files changed, 157 insertions(+), 8 deletions(-) diff --git a/KitX.Loader.CSharp/ArgsParser.cs b/KitX.Loader.CSharp/ArgsParser.cs index a6d7f36..94605c1 100644 --- a/KitX.Loader.CSharp/ArgsParser.cs +++ b/KitX.Loader.CSharp/ArgsParser.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; using CommandLine; namespace KitX.Loader.CSharp; @@ -41,6 +42,10 @@ public static Task ParseAsync(string[] args) private static async Task ParseOptionAsync(Options option) { + Console.WriteLine($"[DEBUG] ArgsParser: PluginPath = {option.PluginPath}"); + Console.WriteLine($"[DEBUG] ArgsParser: ConnectUrl = {option.ConnectUrl}"); + Console.WriteLine($"[DEBUG] ArgsParser: WorkingDirectory = {option.WorkingDirectory}"); + if (option.PluginPath is null) return; @@ -50,8 +55,24 @@ private static async Task ParseOptionAsync(Options option) var communicationManager = new CommunicationManager(); if (option.ConnectUrl is not null) - communicationManager = await communicationManager.Connect(option.ConnectUrl); - else communicationManager = null; + { + Console.WriteLine($"[DEBUG] Connecting to {option.ConnectUrl}..."); + try + { + communicationManager = await communicationManager.Connect(option.ConnectUrl); + Console.WriteLine($"[DEBUG] Connected successfully!"); + } + catch (Exception ex) + { + Console.WriteLine($"[DEBUG] Connection failed: {ex.Message}"); + Console.WriteLine($"[DEBUG] Stack trace: {ex.StackTrace}"); + } + } + else + { + Console.WriteLine("[DEBUG] No ConnectUrl provided, running without connection"); + communicationManager = null; + } var pluginManager = new PluginManager() .OnSendMessage(x => communicationManager?.SendMessageAsync(x)) @@ -59,5 +80,25 @@ private static async Task ParseOptionAsync(Options option) if (communicationManager is not null) communicationManager.OnReceiveMessage = x => pluginManager.ReceiveMessage(x); + + // === 进程保活:等待退出信号 === + var exitSignal = new ManualResetEventSlim(false); + + // 响应 Ctrl+C / Ctrl+Break + Console.CancelKeyPress += (_, e) => + { + e.Cancel = true; + exitSignal.Set(); + }; + + // 响应进程终止事件 + AppDomain.CurrentDomain.ProcessExit += (_, _) => exitSignal.Set(); + + // 等待退出信号 + exitSignal.Wait(); + + // 优雅退出:关闭 WebSocket 连接 + if (communicationManager is not null) + await communicationManager.Close(); } } diff --git a/KitX.Loader.CSharp/CommunicationManager.cs b/KitX.Loader.CSharp/CommunicationManager.cs index 7c2440d..66aeaea 100644 --- a/KitX.Loader.CSharp/CommunicationManager.cs +++ b/KitX.Loader.CSharp/CommunicationManager.cs @@ -20,44 +20,80 @@ public CommunicationManager() public async Task Connect(string? url) { + Console.WriteLine($"[DEBUG] CommunicationManager.Connect: Starting connection to {url}"); + ArgumentNullException.ThrowIfNull(url, nameof(url)); - ArgumentNullException.ThrowIfNull(Client, nameof(Client)); + if (Client is null) + { + Console.WriteLine($"[DEBUG] CommunicationManager.Connect: Client is NULL!"); + throw new InvalidOperationException("ClientWebSocket is not initialized"); + } - await Client.ConnectAsync(new Uri(url), CancellationToken.None); + Console.WriteLine($"[DEBUG] CommunicationManager.Connect: Client state before connect: {Client.State}"); + + try + { + Console.WriteLine($"[DEBUG] CommunicationManager.Connect: Calling ConnectAsync..."); + await Client.ConnectAsync(new Uri(url), CancellationToken.None); + Console.WriteLine($"[DEBUG] CommunicationManager.Connect: ConnectAsync completed, state: {Client.State}"); + } + catch (Exception ex) + { + Console.WriteLine($"[DEBUG] CommunicationManager.Connect: ConnectAsync failed: {ex.Message}"); + Console.WriteLine($"[DEBUG] CommunicationManager.Connect: Stack trace: {ex.StackTrace}"); + throw; + } var waiting = true; var timeout = DateTime.Now.AddSeconds(30); // 30 second timeout + Console.WriteLine($"[DEBUG] CommunicationManager.Connect: Waiting for connection open, initial state: {Client.State}"); + while (waiting && DateTime.Now < timeout) { switch (Client.State) { case WebSocketState.None: + Console.WriteLine($"[DEBUG] CommunicationManager.Connect: State = None"); waiting = false; break; case WebSocketState.Connecting: + Console.WriteLine($"[DEBUG] CommunicationManager.Connect: State = Connecting..."); await Task.Delay(10); // Wait a bit before checking again break; case WebSocketState.Open: + Console.WriteLine($"[DEBUG] CommunicationManager.Connect: State = Open!"); _ = ReceiveAsync(); // Start receiving in background waiting = false; break; case WebSocketState.CloseSent: + Console.WriteLine($"[DEBUG] CommunicationManager.Connect: State = CloseSent"); waiting = false; break; case WebSocketState.CloseReceived: + Console.WriteLine($"[DEBUG] CommunicationManager.Connect: State = CloseReceived"); waiting = false; break; case WebSocketState.Closed: + Console.WriteLine($"[DEBUG] CommunicationManager.Connect: State = Closed"); waiting = false; break; case WebSocketState.Aborted: + Console.WriteLine($"[DEBUG] CommunicationManager.Connect: State = Aborted"); waiting = false; break; } } + if (Client.State != WebSocketState.Open) + { + Console.WriteLine($"[DEBUG] CommunicationManager.Connect: Failed to connect, final state: {Client.State}"); + throw new InvalidOperationException($"WebSocket failed to connect, state: {Client.State}"); + } + + Console.WriteLine($"[DEBUG] CommunicationManager.Connect: Connection established!"); + return this; } diff --git a/KitX.Loader.CSharp/PluginManager.cs b/KitX.Loader.CSharp/PluginManager.cs index 56e0205..3474ac3 100644 --- a/KitX.Loader.CSharp/PluginManager.cs +++ b/KitX.Loader.CSharp/PluginManager.cs @@ -76,11 +76,22 @@ private void InitPlugin(IIdentityInterface plugin) { pluginInfo = plugin.GetPluginInfo(); + Console.WriteLine($"[DEBUG] InitPlugin called, sendMessageAction is: {(sendMessageAction is null ? "NULL" : "SET")}"); + var pluginInfoToSend = Encoding.UTF8.GetBytes( JsonSerializer.Serialize(pluginInfo, serializerOptions) ); - Connector.Request().RegisterPlugin(pluginInfoToSend, pluginInfoToSend.Length).Send(); + Console.WriteLine($"[DEBUG] Sending RegisterPlugin request..."); + try + { + Connector.Request().RegisterPlugin(pluginInfoToSend, pluginInfoToSend.Length).Send(); + Console.WriteLine($"[DEBUG] RegisterPlugin sent successfully"); + } + catch (Exception ex) + { + Console.WriteLine($"[DEBUG] RegisterPlugin failed: {ex.Message}"); + } controller = plugin.GetController(); @@ -91,7 +102,11 @@ private void InitPlugin(IIdentityInterface plugin) controller.Start(); } - private void SendMessage(string message) => sendMessageAction?.Invoke(message); + private void SendMessage(string message) + { + Console.WriteLine($"[DEBUG] SendMessage called, action is: {(sendMessageAction is null ? "NULL" : "SET")}"); + sendMessageAction?.Invoke(message); + } public void ReceiveMessage(string message) { @@ -116,8 +131,49 @@ public void ReceiveMessage(string message) case CommandRequestInfo.ReceiveCommand: + // 保存原始 RequestId 和 ConnectionId 用于响应 + string? requestId = null; + string? pluginConnectionId = command.PluginConnectionId; + if (command.Tags is not null && command.Tags.TryGetValue("RequestId", out var reqId)) + { + requestId = reqId; + } + + // 执行命令 controller?.Execute(command); + // 如果有 RequestId,发送响应 + if (requestId is not null) + { + // 构建响应消息 + var responseBody = $"Hello, {command.FunctionArgs?[0].Value ?? "World"}!"; + var responseBytes = Encoding.UTF8.GetBytes(responseBody); + + Console.WriteLine($"[DEBUG] Sending response: {responseBody}"); + + var responseCommand = new Command + { + Request = CommandRequestInfo.ReceiveCommand, + PluginConnectionId = pluginConnectionId ?? string.Empty, + Body = responseBytes, + BodyLength = responseBytes.Length, + Tags = new Dictionary + { + { "RequestId", requestId } + } + }; + + var responseRequest = new Request + { + Content = JsonSerializer.Serialize(responseCommand, serializerOptions) + }; + + var responseJson = JsonSerializer.Serialize(responseRequest, serializerOptions); + Console.WriteLine($"[DEBUG] Response JSON: {responseJson.Substring(0, Math.Min(200, responseJson.Length))}..."); + + SendMessage(responseJson); + } + break; } } diff --git a/KitX.Loader.CSharp/Program.cs b/KitX.Loader.CSharp/Program.cs index 6a6dd25..c01f8af 100644 --- a/KitX.Loader.CSharp/Program.cs +++ b/KitX.Loader.CSharp/Program.cs @@ -1,3 +1,19 @@ using KitX.Loader.CSharp; +using System.Threading.Tasks; -ArgsParser.Parse(args); +// 全局异常处理 +AppDomain.CurrentDomain.UnhandledException += (_, e) => +{ + Console.WriteLine($"[FATAL] Unhandled exception: {e.ExceptionObject}"); + Console.WriteLine($"[FATAL] Stack trace: {(e.ExceptionObject as Exception)?.StackTrace}"); + Environment.Exit(1); +}; + +TaskScheduler.UnobservedTaskException += (_, e) => +{ + Console.WriteLine($"[ERROR] Unobserved task exception: {e.Exception.Message}"); + e.SetObserved(); +}; + +// 使用同步方式阻塞等待异步解析完成 +ArgsParser.ParseAsync(args).GetAwaiter().GetResult(); From 672031c6043271b25b745a3f877a3225643506bd Mon Sep 17 00:00:00 2001 From: StarInk Date: Sun, 15 Mar 2026 14:28:36 +0100 Subject: [PATCH 3/5] =?UTF-8?q?=F0=9F=94=A7=20Fix(KitX.Loader.CSharp):=20?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E7=A1=AC=E7=BC=96=E7=A0=81=E7=9A=84=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E9=80=BB=E8=BE=91=EF=BC=8C=E4=BD=BF=E7=94=A8=E5=9F=BA?= =?UTF-8?q?=E4=BA=8ERequestId=E7=9A=84=E8=B0=83=E7=94=A8=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- KitX.Loader.CSharp/PluginManager.cs | 42 +---------------------------- 1 file changed, 1 insertion(+), 41 deletions(-) diff --git a/KitX.Loader.CSharp/PluginManager.cs b/KitX.Loader.CSharp/PluginManager.cs index 3474ac3..6f3bd20 100644 --- a/KitX.Loader.CSharp/PluginManager.cs +++ b/KitX.Loader.CSharp/PluginManager.cs @@ -131,49 +131,9 @@ public void ReceiveMessage(string message) case CommandRequestInfo.ReceiveCommand: - // 保存原始 RequestId 和 ConnectionId 用于响应 - string? requestId = null; - string? pluginConnectionId = command.PluginConnectionId; - if (command.Tags is not null && command.Tags.TryGetValue("RequestId", out var reqId)) - { - requestId = reqId; - } - - // 执行命令 + // 执行命令 - 插件通过 sendCommandAction 发送响应 controller?.Execute(command); - // 如果有 RequestId,发送响应 - if (requestId is not null) - { - // 构建响应消息 - var responseBody = $"Hello, {command.FunctionArgs?[0].Value ?? "World"}!"; - var responseBytes = Encoding.UTF8.GetBytes(responseBody); - - Console.WriteLine($"[DEBUG] Sending response: {responseBody}"); - - var responseCommand = new Command - { - Request = CommandRequestInfo.ReceiveCommand, - PluginConnectionId = pluginConnectionId ?? string.Empty, - Body = responseBytes, - BodyLength = responseBytes.Length, - Tags = new Dictionary - { - { "RequestId", requestId } - } - }; - - var responseRequest = new Request - { - Content = JsonSerializer.Serialize(responseCommand, serializerOptions) - }; - - var responseJson = JsonSerializer.Serialize(responseRequest, serializerOptions); - Console.WriteLine($"[DEBUG] Response JSON: {responseJson.Substring(0, Math.Min(200, responseJson.Length))}..."); - - SendMessage(responseJson); - } - break; } } From 1f84fb0b7373ed53a3d516d694cb8890feb4a09b Mon Sep 17 00:00:00 2001 From: StarInk Date: Mon, 13 Apr 2026 02:45:12 +0200 Subject: [PATCH 4/5] =?UTF-8?q?=F0=9F=92=BE=20Feat:=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E9=9D=9E=E9=98=BB=E5=A1=9E=E6=8F=92=E4=BB=B6=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=EF=BC=8C=E4=BC=98=E5=8C=96=20WPF=20=E5=BA=94?= =?UTF-8?q?=E7=94=A8=E7=9A=84=E8=BF=9B=E7=A8=8B=E7=94=9F=E5=91=BD=E5=91=A8?= =?UTF-8?q?=E6=9C=9F=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- KitX.Loader.CSharp/ArgsParser.cs | 56 ++++++++++++++++++++++++++++++++ KitX.Loader.WPF.Core/App.xaml | 3 +- KitX.Loader.WPF.Core/App.xaml.cs | 24 ++++++++++++-- 3 files changed, 79 insertions(+), 4 deletions(-) diff --git a/KitX.Loader.CSharp/ArgsParser.cs b/KitX.Loader.CSharp/ArgsParser.cs index 94605c1..281fc22 100644 --- a/KitX.Loader.CSharp/ArgsParser.cs +++ b/KitX.Loader.CSharp/ArgsParser.cs @@ -101,4 +101,60 @@ private static async Task ParseOptionAsync(Options option) if (communicationManager is not null) await communicationManager.Close(); } + + /// + /// 仅执行插件加载和连接,不阻塞等待退出信号。 + /// 适用于有自身消息循环的宿主(如 WPF),由宿主管理进程生命周期。 + /// + /// 命令行参数 + /// 用于优雅关闭的 CommunicationManager 实例 + public static async Task LoadWithoutBlockingAsync(string[] args) + { + CommunicationManager? communicationManager = null; + + Parser.Default.ParseArguments(args) + .WithParsed(async option => + { + Console.WriteLine($"[DEBUG] ArgsParser: PluginPath = {option.PluginPath}"); + Console.WriteLine($"[DEBUG] ArgsParser: ConnectUrl = {option.ConnectUrl}"); + Console.WriteLine($"[DEBUG] ArgsParser: WorkingDirectory = {option.WorkingDirectory}"); + + if (option.PluginPath is null) + return; + + if (option.WorkingDirectory is not null) + Directory.SetCurrentDirectory(option.WorkingDirectory); + + communicationManager = new CommunicationManager(); + + if (option.ConnectUrl is not null) + { + Console.WriteLine($"[DEBUG] Connecting to {option.ConnectUrl}..."); + try + { + communicationManager = await communicationManager.Connect(option.ConnectUrl); + Console.WriteLine($"[DEBUG] Connected successfully!"); + } + catch (Exception ex) + { + Console.WriteLine($"[DEBUG] Connection failed: {ex.Message}"); + communicationManager = null; + } + } + else + { + Console.WriteLine("[DEBUG] No ConnectUrl provided, running without connection"); + communicationManager = null; + } + + var pluginManager = new PluginManager() + .OnSendMessage(x => communicationManager?.SendMessageAsync(x)) + .LoadPlugin(option.PluginPath); + + if (communicationManager is not null) + communicationManager.OnReceiveMessage = x => pluginManager.ReceiveMessage(x); + }); + + return communicationManager; + } } diff --git a/KitX.Loader.WPF.Core/App.xaml b/KitX.Loader.WPF.Core/App.xaml index 3b526de..ac049e8 100644 --- a/KitX.Loader.WPF.Core/App.xaml +++ b/KitX.Loader.WPF.Core/App.xaml @@ -2,7 +2,8 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:KitX.Loader.WPF.Core" - Startup="Application_Startup"> + Startup="Application_Startup" + Exit="Application_Exit"> diff --git a/KitX.Loader.WPF.Core/App.xaml.cs b/KitX.Loader.WPF.Core/App.xaml.cs index 3248a71..b512344 100644 --- a/KitX.Loader.WPF.Core/App.xaml.cs +++ b/KitX.Loader.WPF.Core/App.xaml.cs @@ -1,5 +1,4 @@ -using System; -using System.Threading.Tasks; +using System; using System.Windows; using KitX.Loader.CSharp; @@ -7,11 +6,14 @@ namespace KitX.Loader.WPF.Core; public partial class App : Application { + private CommunicationManager? _communicationManager; + private async void Application_Startup(object sender, StartupEventArgs e) { try { - await ArgsParser.ParseAsync(e.Args); + // 使用非阻塞方式加载插件,WPF 自身的消息循环管理进程生命周期 + _communicationManager = await ArgsParser.LoadWithoutBlockingAsync(e.Args); } catch (Exception o) { @@ -27,4 +29,20 @@ private async void Application_Startup(object sender, StartupEventArgs e) Environment.Exit(1); } } + + private async void Application_Exit(object sender, ExitEventArgs e) + { + // 优雅退出:关闭 WebSocket 连接 + if (_communicationManager is not null) + { + try + { + await _communicationManager.Close(); + } + catch (Exception ex) + { + Console.WriteLine($"[DEBUG] Error closing communication: {ex.Message}"); + } + } + } } From 5bb1d78ecc287b3ad986119b3aa7448da78b5616 Mon Sep 17 00:00:00 2001 From: StarInk Date: Sun, 3 May 2026 01:14:51 +0200 Subject: [PATCH 5/5] =?UTF-8?q?=F0=9F=94=A7=20Fix:=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E6=96=87=E4=BB=B6=E4=BB=A5=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=20.NET=2010.0=20=E4=BD=9C=E4=B8=BA=E7=9B=AE=E6=A0=87=E6=A1=86?= =?UTF-8?q?=E6=9E=B6=E5=B9=B6=E4=BF=AE=E5=A4=8Dclr=E6=9C=AA=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E5=AF=BC=E8=87=B4.Net=2010=E7=8E=AF=E5=A2=83=E4=B8=8B?= =?UTF-8?q?=E9=9D=99=E9=BB=98=E9=80=80=E5=87=BA=E7=9A=84=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- KitX.Loader.CSharp/KitX.Loader.CSharp.csproj | 2 +- KitX.Loader.WPF.Core/App.xaml | 3 +-- KitX.Loader.WPF.Core/KitX.Loader.WPF.Core.csproj | 2 +- KitX.Loader.Winform.Core/KitX.Loader.Winform.Core.csproj | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/KitX.Loader.CSharp/KitX.Loader.CSharp.csproj b/KitX.Loader.CSharp/KitX.Loader.CSharp.csproj index 1c5469f..a14e0d5 100644 --- a/KitX.Loader.CSharp/KitX.Loader.CSharp.csproj +++ b/KitX.Loader.CSharp/KitX.Loader.CSharp.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net10.0 enable enable diff --git a/KitX.Loader.WPF.Core/App.xaml b/KitX.Loader.WPF.Core/App.xaml index ac049e8..6dfe557 100644 --- a/KitX.Loader.WPF.Core/App.xaml +++ b/KitX.Loader.WPF.Core/App.xaml @@ -1,10 +1,9 @@  - + diff --git a/KitX.Loader.WPF.Core/KitX.Loader.WPF.Core.csproj b/KitX.Loader.WPF.Core/KitX.Loader.WPF.Core.csproj index 09cfc24..e1c661f 100644 --- a/KitX.Loader.WPF.Core/KitX.Loader.WPF.Core.csproj +++ b/KitX.Loader.WPF.Core/KitX.Loader.WPF.Core.csproj @@ -2,7 +2,7 @@ WinExe - net8.0-windows + net10.0-windows enable true diff --git a/KitX.Loader.Winform.Core/KitX.Loader.Winform.Core.csproj b/KitX.Loader.Winform.Core/KitX.Loader.Winform.Core.csproj index 5b397b9..5f89d89 100644 --- a/KitX.Loader.Winform.Core/KitX.Loader.Winform.Core.csproj +++ b/KitX.Loader.Winform.Core/KitX.Loader.Winform.Core.csproj @@ -2,7 +2,7 @@ WinExe - net8.0-windows + net10.0-windows enable true enable