From 299e9d706e9929f1e29e8982c03b06ca7e278f0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=9B=BD=E4=BC=9F?= <366193849@qq.com> Date: Mon, 25 Oct 2021 17:37:34 +0800 Subject: [PATCH] =?UTF-8?q?=E9=9B=86=E6=88=90winform?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Directory.Build.props | 3 +- .../FastGithub.Configuration.csproj | 5 +- .../FastGithub.DomainResolve.csproj | 5 +- FastGithub.Http/FastGithub.Http.csproj | 7 +- .../FastGithub.HttpServer.csproj | 3 +- .../FastGithub.PacketIntercept.csproj | 1 + FastGithub.Upgrade/FastGithub.Upgrade.csproj | 7 ++ .../ProductionVersion.cs | 2 +- FastGithub.Windows/FastGithub.Windows.csproj | 13 +++ FastGithub.Windows/Forms/MainForm.Designer.cs | 47 ++++++++++ FastGithub.Windows/Forms/MainForm.cs | 20 +++++ FastGithub.Windows/Forms/MainForm.resx | 60 +++++++++++++ .../Hosting/ApplicationOptions.cs | 25 ++++++ .../Hosting/IWinFormDispatcher.cs | 51 +++++++++++ .../Hosting/WinFormDispatcher.cs | 15 ++++ .../Hosting/WinFormHostBuilderExtensions.cs | 63 +++++++++++++ .../Hosting/WinFormHostLifetime.cs | 55 ++++++++++++ .../Hosting/WinFormHostedService.cs | 88 +++++++++++++++++++ .../ServiceCollectionExtensions.cs | 22 +++++ FastGithub.sln | 12 +++ FastGithub/AppHostedService.cs | 1 + FastGithub/FastGithub.csproj | 17 +++- FastGithub/Program.cs | 4 + 23 files changed, 517 insertions(+), 9 deletions(-) create mode 100644 FastGithub.Upgrade/FastGithub.Upgrade.csproj rename {FastGithub => FastGithub.Upgrade}/ProductionVersion.cs (99%) create mode 100644 FastGithub.Windows/FastGithub.Windows.csproj create mode 100644 FastGithub.Windows/Forms/MainForm.Designer.cs create mode 100644 FastGithub.Windows/Forms/MainForm.cs create mode 100644 FastGithub.Windows/Forms/MainForm.resx create mode 100644 FastGithub.Windows/Hosting/ApplicationOptions.cs create mode 100644 FastGithub.Windows/Hosting/IWinFormDispatcher.cs create mode 100644 FastGithub.Windows/Hosting/WinFormDispatcher.cs create mode 100644 FastGithub.Windows/Hosting/WinFormHostBuilderExtensions.cs create mode 100644 FastGithub.Windows/Hosting/WinFormHostLifetime.cs create mode 100644 FastGithub.Windows/Hosting/WinFormHostedService.cs create mode 100644 FastGithub.Windows/ServiceCollectionExtensions.cs diff --git a/Directory.Build.props b/Directory.Build.props index e4073a7..ebc26e3 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,8 +4,7 @@ enable github加速神器 https://github.com/dotnetcore/FastGithub - win-x64 - net6.0 + win-x64 true true diff --git a/FastGithub.Configuration/FastGithub.Configuration.csproj b/FastGithub.Configuration/FastGithub.Configuration.csproj index 94918f0..b469e5e 100644 --- a/FastGithub.Configuration/FastGithub.Configuration.csproj +++ b/FastGithub.Configuration/FastGithub.Configuration.csproj @@ -1,5 +1,8 @@  - + + net6.0 + + diff --git a/FastGithub.DomainResolve/FastGithub.DomainResolve.csproj b/FastGithub.DomainResolve/FastGithub.DomainResolve.csproj index 0ad99be..2c92ada 100644 --- a/FastGithub.DomainResolve/FastGithub.DomainResolve.csproj +++ b/FastGithub.DomainResolve/FastGithub.DomainResolve.csproj @@ -1,5 +1,8 @@  - + + net6.0 + + diff --git a/FastGithub.Http/FastGithub.Http.csproj b/FastGithub.Http/FastGithub.Http.csproj index 655769c..ad52c1e 100644 --- a/FastGithub.Http/FastGithub.Http.csproj +++ b/FastGithub.Http/FastGithub.Http.csproj @@ -1,5 +1,8 @@ - - + + + net6.0 + + diff --git a/FastGithub.HttpServer/FastGithub.HttpServer.csproj b/FastGithub.HttpServer/FastGithub.HttpServer.csproj index 46bc77d..51b1802 100644 --- a/FastGithub.HttpServer/FastGithub.HttpServer.csproj +++ b/FastGithub.HttpServer/FastGithub.HttpServer.csproj @@ -1,6 +1,7 @@  - + + net6.0 true diff --git a/FastGithub.PacketIntercept/FastGithub.PacketIntercept.csproj b/FastGithub.PacketIntercept/FastGithub.PacketIntercept.csproj index 2c8b98c..e9fa703 100644 --- a/FastGithub.PacketIntercept/FastGithub.PacketIntercept.csproj +++ b/FastGithub.PacketIntercept/FastGithub.PacketIntercept.csproj @@ -1,6 +1,7 @@  + net6.0 true diff --git a/FastGithub.Upgrade/FastGithub.Upgrade.csproj b/FastGithub.Upgrade/FastGithub.Upgrade.csproj new file mode 100644 index 0000000..0a94a8d --- /dev/null +++ b/FastGithub.Upgrade/FastGithub.Upgrade.csproj @@ -0,0 +1,7 @@ + + + + net6.0 + + + diff --git a/FastGithub/ProductionVersion.cs b/FastGithub.Upgrade/ProductionVersion.cs similarity index 99% rename from FastGithub/ProductionVersion.cs rename to FastGithub.Upgrade/ProductionVersion.cs index 2b8fb70..5a757d1 100644 --- a/FastGithub/ProductionVersion.cs +++ b/FastGithub.Upgrade/ProductionVersion.cs @@ -2,7 +2,7 @@ using System.Reflection; using System.Text.RegularExpressions; -namespace FastGithub +namespace FastGithub.Upgrade { /// /// 表示产品版本 diff --git a/FastGithub.Windows/FastGithub.Windows.csproj b/FastGithub.Windows/FastGithub.Windows.csproj new file mode 100644 index 0000000..1a723e1 --- /dev/null +++ b/FastGithub.Windows/FastGithub.Windows.csproj @@ -0,0 +1,13 @@ + + + + net6.0-windows + true + + + + + + + + diff --git a/FastGithub.Windows/Forms/MainForm.Designer.cs b/FastGithub.Windows/Forms/MainForm.Designer.cs new file mode 100644 index 0000000..0b8aeec --- /dev/null +++ b/FastGithub.Windows/Forms/MainForm.Designer.cs @@ -0,0 +1,47 @@ +namespace FastGithub.Windows.Forms +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(11F, 24F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(800, 450); + this.Name = "MainForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "FastGithub"; + this.ResumeLayout(false); + + } + + #endregion + } +} \ No newline at end of file diff --git a/FastGithub.Windows/Forms/MainForm.cs b/FastGithub.Windows/Forms/MainForm.cs new file mode 100644 index 0000000..864fec7 --- /dev/null +++ b/FastGithub.Windows/Forms/MainForm.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace FastGithub.Windows.Forms +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + } + } +} diff --git a/FastGithub.Windows/Forms/MainForm.resx b/FastGithub.Windows/Forms/MainForm.resx new file mode 100644 index 0000000..f298a7b --- /dev/null +++ b/FastGithub.Windows/Forms/MainForm.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/FastGithub.Windows/Hosting/ApplicationOptions.cs b/FastGithub.Windows/Hosting/ApplicationOptions.cs new file mode 100644 index 0000000..1a95761 --- /dev/null +++ b/FastGithub.Windows/Hosting/ApplicationOptions.cs @@ -0,0 +1,25 @@ +using System.Windows.Forms; + +namespace FastGithub.Windows.Hosting +{ + /// + /// 表示Application选项 + /// + public class ApplicationOptions + { + /// + /// 获取或设置是否启用VisualStyles + /// + public bool EnableVisualStyles { get; set; } = true; + + /// + /// 获取或设置高Dpi的模式 + /// + public HighDpiMode HighDpiMode { get; set; } = HighDpiMode.SystemAware; + + /// + /// 获取或设置是否兼容TextRendering + /// + public bool CompatibleTextRenderingDefault { get; set; } = false; + } +} diff --git a/FastGithub.Windows/Hosting/IWinFormDispatcher.cs b/FastGithub.Windows/Hosting/IWinFormDispatcher.cs new file mode 100644 index 0000000..6e74be7 --- /dev/null +++ b/FastGithub.Windows/Hosting/IWinFormDispatcher.cs @@ -0,0 +1,51 @@ +using System; +using System.Threading; + +namespace FastGithub.Windows.Hosting +{ + /// + /// WinForm调度器 + /// + public interface IWinFormDispatcher + { + /// + /// 获取或设置同步上下文 + /// + SynchronizationContext? SynchronizationContext { get; set; } + + /// + /// 尝试在同步上下文投递执行委托 + /// + /// + /// + bool TryInvoke(Action action) + { + var context = this.SynchronizationContext; + if (context == null || action == null) + { + return false; + } + + context.Post(state => ((Action)state!)(), action); + return false; + } + + /// + /// 在同步上下文投递执行委托 + /// + /// + void Invoke(Action action) + { + var context = this.SynchronizationContext; + if (context == null) + { + throw new InvalidOperationException($"{nameof(SynchronizationContext)} is null"); + } + + if (action != null) + { + context.Post(state => ((Action)state!)(), action); + } + } + } +} diff --git a/FastGithub.Windows/Hosting/WinFormDispatcher.cs b/FastGithub.Windows/Hosting/WinFormDispatcher.cs new file mode 100644 index 0000000..9afecb5 --- /dev/null +++ b/FastGithub.Windows/Hosting/WinFormDispatcher.cs @@ -0,0 +1,15 @@ +using System.Threading; + +namespace FastGithub.Windows.Hosting +{ + /// + /// WinForm调度器 + /// + sealed class WinFormDispatcher : IWinFormDispatcher + { + /// + /// 获取或设置同步上下文 + /// + public SynchronizationContext? SynchronizationContext { get; set; } + } +} diff --git a/FastGithub.Windows/Hosting/WinFormHostBuilderExtensions.cs b/FastGithub.Windows/Hosting/WinFormHostBuilderExtensions.cs new file mode 100644 index 0000000..3b4c959 --- /dev/null +++ b/FastGithub.Windows/Hosting/WinFormHostBuilderExtensions.cs @@ -0,0 +1,63 @@ +using FastGithub.Windows.Hosting; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Windows.Forms; + +namespace Microsoft.Extensions.Hosting +{ + /// + /// IHostBuilder的WinForm扩展 + /// + public static class WinFormHostBuilderExtensions + { + /// + /// 指定WinForm的主窗体 + /// + /// + /// * 该方法需要在services.AddHostedService()之前调用 + /// + /// + /// + /// + public static IHostBuilder UseWinForm(this IHostBuilder hostBuilder) where TMainForm : Form + { + return hostBuilder.ConfigureServices((context, services) => + { + services + .AddSingleton() + .AddSingleton() + .AddHostedService>(); + }); + } + + /// + /// 使用WinForm生命周期 + /// + /// + /// * 关闭主窗体或调用Appliaction.Exit()之后生命结束 + /// + /// + /// + public static IHostBuilder UseWinFormHostLifetime(this IHostBuilder hostBuilder) + { + return hostBuilder.UseWinFormHostLifetime(c => { }); + } + + /// + /// 使用WinForm生命周期 + /// + /// + /// * 关闭主窗体或调用Appliaction.Exit()之后生命结束 + /// + /// + /// Applicaiton选项 + public static IHostBuilder UseWinFormHostLifetime(this IHostBuilder hostBuilder, Action configureOptions) + { + return hostBuilder.ConfigureServices((context, services) => + { + services.Configure(configureOptions); + services.AddSingleton(); + }); + } + } +} diff --git a/FastGithub.Windows/Hosting/WinFormHostLifetime.cs b/FastGithub.Windows/Hosting/WinFormHostLifetime.cs new file mode 100644 index 0000000..91b1624 --- /dev/null +++ b/FastGithub.Windows/Hosting/WinFormHostLifetime.cs @@ -0,0 +1,55 @@ +using FastGithub.Windows.Hosting; +using Microsoft.Extensions.Options; +using System; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace Microsoft.Extensions.Hosting +{ + /// + /// WinForm生命周期 + /// + sealed class WinFormHostLifetime : IHostLifetime, IDisposable + { + private readonly IHostApplicationLifetime applicationLifetime; + private readonly IOptions applicationOptions; + + public WinFormHostLifetime(IHostApplicationLifetime applicationLifetime, IOptions applicationOptions) + { + this.applicationLifetime = applicationLifetime; + this.applicationOptions = applicationOptions; + } + + public Task WaitForStartAsync(CancellationToken cancellationToken) + { + var option = this.applicationOptions.Value; + if (option.EnableVisualStyles == true) + { + Application.EnableVisualStyles(); + } + + Application.SetHighDpiMode(option.HighDpiMode); + Application.SetCompatibleTextRenderingDefault(option.CompatibleTextRenderingDefault); + + Application.ApplicationExit += OnApplicationExit; + return Task.CompletedTask; + } + + private void OnApplicationExit(object? sender, System.EventArgs e) + { + Application.ApplicationExit -= OnApplicationExit; + this.applicationLifetime.StopApplication(); + } + + public Task StopAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } + + public void Dispose() + { + Application.ApplicationExit -= OnApplicationExit; + } + } +} diff --git a/FastGithub.Windows/Hosting/WinFormHostedService.cs b/FastGithub.Windows/Hosting/WinFormHostedService.cs new file mode 100644 index 0000000..b7b4f48 --- /dev/null +++ b/FastGithub.Windows/Hosting/WinFormHostedService.cs @@ -0,0 +1,88 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using System; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace FastGithub.Windows.Hosting +{ + /// + /// WinForm后台任务和WinForm线程 + /// + /// + sealed class WinFormHostedService : IHostedService where TMainForm : Form + { + private readonly Thread staThread; + private readonly IServiceProvider serviceProvider; + private readonly TaskCompletionSource taskCompletionSource = new(); + + /// + /// WinForm后台任务 + /// + /// + public WinFormHostedService(IServiceProvider serviceProvider) + { + this.serviceProvider = serviceProvider; + this.staThread = new Thread(StaRunMainFrom); + this.staThread.TrySetApartmentState(ApartmentState.STA); + } + + /// + /// 启动 + /// + /// + /// + public Task StartAsync(CancellationToken cancellationToken) + { + this.staThread.Start(); + return this.taskCompletionSource.Task; + } + + /// + /// STA线程 + /// + private void StaRunMainFrom() + { + try + { + var mainForm = this.CreateMainForm(); + this.taskCompletionSource.TrySetResult(); + Application.Run(mainForm); + } + catch (Exception ex) + { + this.taskCompletionSource.TrySetException(ex); + } + } + + /// + /// 实例化MainForm与初始化调度器 + /// + /// + private TMainForm CreateMainForm() + { + // 在STA线程实例化TMainForm,保证该线程拥有SynchronizationContext + var mainForm = this.serviceProvider.GetRequiredService(); + if (SynchronizationContext.Current is null) + { + throw new InvalidOperationException($"不允许在其它线程上实例化{typeof(TMainForm)}"); + } + + var dispatcher = this.serviceProvider.GetRequiredService(); + dispatcher.SynchronizationContext = SynchronizationContext.Current; + return mainForm; + } + + /// + /// 停止 + /// + /// + /// + public Task StopAsync(CancellationToken cancellationToken) + { + Application.Exit(); + return Task.CompletedTask; + } + } +} diff --git a/FastGithub.Windows/ServiceCollectionExtensions.cs b/FastGithub.Windows/ServiceCollectionExtensions.cs new file mode 100644 index 0000000..3c1cc8b --- /dev/null +++ b/FastGithub.Windows/ServiceCollectionExtensions.cs @@ -0,0 +1,22 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Logging; + +namespace FastGithub +{ + /// + /// 服务注册扩展 + /// + public static class ServiceCollectionExtensions + { + /// + /// 添加配置服务 + /// + /// + /// + public static IServiceCollection AddWinForm(this IServiceCollection services) + { + return services; + } + } +} diff --git a/FastGithub.sln b/FastGithub.sln index 0e19d20..8ade0bc 100644 --- a/FastGithub.sln +++ b/FastGithub.sln @@ -15,6 +15,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FastGithub.HttpServer", "Fa EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FastGithub.PacketIntercept", "FastGithub.PacketIntercept\FastGithub.PacketIntercept.csproj", "{701FF90C-E651-4E0B-AE7F-84D1F17DD178}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FastGithub.Windows", "FastGithub.Windows\FastGithub.Windows.csproj", "{4F9914B7-2519-46F9-96F1-42400B6BFD6E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FastGithub.Upgrade", "FastGithub.Upgrade\FastGithub.Upgrade.csproj", "{D644B53B-91E4-41DD-818B-FE3A77ED8D10}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -45,6 +49,14 @@ Global {701FF90C-E651-4E0B-AE7F-84D1F17DD178}.Debug|Any CPU.Build.0 = Debug|Any CPU {701FF90C-E651-4E0B-AE7F-84D1F17DD178}.Release|Any CPU.ActiveCfg = Release|Any CPU {701FF90C-E651-4E0B-AE7F-84D1F17DD178}.Release|Any CPU.Build.0 = Release|Any CPU + {4F9914B7-2519-46F9-96F1-42400B6BFD6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4F9914B7-2519-46F9-96F1-42400B6BFD6E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4F9914B7-2519-46F9-96F1-42400B6BFD6E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4F9914B7-2519-46F9-96F1-42400B6BFD6E}.Release|Any CPU.Build.0 = Release|Any CPU + {D644B53B-91E4-41DD-818B-FE3A77ED8D10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D644B53B-91E4-41DD-818B-FE3A77ED8D10}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D644B53B-91E4-41DD-818B-FE3A77ED8D10}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D644B53B-91E4-41DD-818B-FE3A77ED8D10}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/FastGithub/AppHostedService.cs b/FastGithub/AppHostedService.cs index 7baf2fc..796cdfe 100644 --- a/FastGithub/AppHostedService.cs +++ b/FastGithub/AppHostedService.cs @@ -1,4 +1,5 @@ using FastGithub.Configuration; +using FastGithub.Upgrade; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; diff --git a/FastGithub/FastGithub.csproj b/FastGithub/FastGithub.csproj index 9b803de..7f8f335 100644 --- a/FastGithub/FastGithub.csproj +++ b/FastGithub/FastGithub.csproj @@ -1,6 +1,7 @@ - + + net6.0;net6.0-windows fastgithub Exe MIT @@ -9,12 +10,26 @@ app.manifest + + true + WinExe + + + + + + + + + + + diff --git a/FastGithub/Program.cs b/FastGithub/Program.cs index f7bfd0c..13947b6 100644 --- a/FastGithub/Program.cs +++ b/FastGithub/Program.cs @@ -27,7 +27,11 @@ namespace FastGithub { return Host .CreateDefaultBuilder(args) +#if WINDOWS .UseWindowsService() + .UseWinForm() + .UseWinFormHostLifetime() +#endif .UseDefaultServiceProvider(c => { c.ValidateOnBuild = false;