diff --git a/example/fileserver/fileserver/Controllers/UpdateController.cs b/example/fileserver/fileserver/Controllers/UpdateController.cs new file mode 100644 index 0000000000000000000000000000000000000000..776d839f3f2193a4c22cdd22822af56783f0d57f --- /dev/null +++ b/example/fileserver/fileserver/Controllers/UpdateController.cs @@ -0,0 +1,153 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using System.Web; +using GeneralUpdate.AspNetCore.Hubs; +using static System.Net.Mime.MediaTypeNames; +using GeneralUpdate.AspNetCore.Services; +using GeneralUpdate.Core.Domain.DTO; +using GeneralUpdate.Core.Domain.Enum; +using GeneralUpdate.Core.Utils; +using GeneralUpdate.AspNetCore.DTO; +using Microsoft.Extensions.Options; +using Newtonsoft.Json; + +namespace GPDI.UpdateService.Controllers +{ + [ApiController] + [Route("api/[controller]/[action]")] + public class UpdateController : ControllerBase + { + private IWebHostEnvironment _webHostEvironment; + private IHttpContextAccessor _accessor; + private IUpdateService _updateService; + private IHubContext _hubContext; + + public UpdateController(IWebHostEnvironment webHostEvironment, IHttpContextAccessor accessor, IUpdateService updateService, IHubContext hubContext) + { + _webHostEvironment = webHostEvironment; + _accessor = accessor; + _updateService = updateService; + _hubContext = hubContext; + } + + //http://localhost:5008/api/Update/test + [HttpGet] + public string Test() + { + return "success"; + } + + + /// + /// 推送强制更新命令给App + /// + /// + [HttpGet] + public async Task Push() + { + //http://localhost:5008/api/Update/push 测试路径 + + await _hubContext.SendMessage("versionhub", "update"); + return "ok"; + } + + [HttpGet] + [Route("/api/update/Versions/{clientType}/{clientVersion}/{clientAppKey}")] + public string Versions(int clientType, string clientVersion, string clientAppKey) + { + //如果是更新程序,直接返回不需要更新,这个不会更新 + if (clientType == AppType.UpgradeApp) + { + return GetUpgradeInfo(clientType, clientVersion); + } + + var versions = new List(); + //生成好的更新包文件的MD5码,因为返回给客户端的时候需要同这个来验证是否可用 + //这个md5可以使用单元测试里面的生成md5获取 + var md5 = "cc9f7189676613b906bd7680ea518f0e"; + var pubTime = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds(); + //这里只会是更新主程序,因为升级程序已经在上面直接返回了 + string version = "1.0.0.9";//这里设置为9是让程序认为需要更新 + + var url = $"http://127.0.0.1:5008/{version}.zip";//更新包的下载地址 + var name = version; + versions.Add(new VersionDTO(md5, pubTime, version, url, name)); + return _updateService.Update(clientType, clientVersion, version, clientAppKey, "B8A7FADD-386C-46B0-B283-C9F963420C7C", false, versions); + + } + + /// + /// 当更新程序来请求时 返回一个不需要更新的对象回去 + /// + /// + /// + private string GetUpgradeInfo(int clientType, string clientVersion) + { + var response = new VersionRespDTO() { }; + response.Body = new VersionBodyDTO() { ClientType = clientType, IsUpdate = false, IsForcibly = false, Versions = new List() { new VersionDTO("111", 0, clientVersion, "http://127.0.0.1:5008/test/", "111") } }; + response.Code = HttpStatus.OK; + response.Message = RespMessage.RequestSucceeded; + return JsonConvert.SerializeObject(response); + } + + /// + /// 上传文件 + /// 重写这个方法里面的插入数据库,就能和旧的联动了 + /// 打包工具上填的地址 http://localhost:5008/api/Update/Upload + /// + /// + [HttpPost] + public async Task Upload() + { + var uploadReapDTO = new UploadReapDTO(); + try + { + //只要调用了此方法,都是工具调用的,必然不可能为null + var request = _accessor.HttpContext.Request; + if (!request.HasFormContentType) throw new Exception("ContentType was not included in the request !"); + var form = await request.ReadFormAsync(); + + var formFile = form.Files["file"]; + + if (formFile is null || formFile.Length == 0) throw new ArgumentNullException("Uploaded update package file not found !"); + await using var stream = formFile.OpenReadStream(); + byte[] buffer = new byte[stream.Length]; + stream.Read(buffer, 0, buffer.Length); + //TODO:save to file server. + string localPath = $"E:\\{formFile.FileName}"; + await using var fileStream = new FileStream(localPath, FileMode.CreateNew, FileAccess.Write); + fileStream.Write(buffer, 0, buffer.Length); + + //TODO oujl 将数据存储到mysql + int.TryParse(request.Form["clientType"], out int clientType); + var fileName = formFile.FileName; + var version = request.Form["version"].ToString(); + var clientAppKey = request.Form["clientAppKey"].ToString(); + var md5 = request.Form["md5"].ToString(); + + + + uploadReapDTO.Code = HttpStatus.OK; + uploadReapDTO.Body = "Published successfully."; + uploadReapDTO.Message = RespMessage.RequestSucceeded; + return JsonConvert.SerializeObject(uploadReapDTO); + } + catch (Exception ex) + { + uploadReapDTO.Code = HttpStatus.BAD_REQUEST; + uploadReapDTO.Body = $"Failed to publish ! Because : {ex.Message}"; + uploadReapDTO.Message = RespMessage.RequestFailed; + return JsonConvert.SerializeObject(uploadReapDTO); + } + } + } +} diff --git a/example/fileserver/fileserver/Program.cs b/example/fileserver/fileserver/Program.cs new file mode 100644 index 0000000000000000000000000000000000000000..77bde957ca53293c79c4d290a62b8e9bba236d35 --- /dev/null +++ b/example/fileserver/fileserver/Program.cs @@ -0,0 +1,26 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace fileserver +{ + public class Program + { + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); + } +} \ No newline at end of file diff --git a/example/fileserver/fileserver/Startup.cs b/example/fileserver/fileserver/Startup.cs new file mode 100644 index 0000000000000000000000000000000000000000..263eb79e386b769d3b36deed56e619dbb55330b9 --- /dev/null +++ b/example/fileserver/fileserver/Startup.cs @@ -0,0 +1,42 @@ +using GeneralUpdate.AspNetCore.Hubs; +using Microsoft.Extensions.DependencyInjection.Extensions; +using GeneralUpdate.AspNetCore.Services; + +namespace fileserver +{ + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + public void ConfigureServices(IServiceCollection services) + { + services.AddSignalR(); + services.AddControllers(); + services.TryAddSingleton(); + services.TryAddSingleton(); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseStaticFiles(); + app.UseRouting(); + + app.UseEndpoints(endpoints => + { + endpoints.MapHub($"/versionhub"); + endpoints.MapControllers(); + }); + } + } +} diff --git a/example/winform/TestWinForms/.vs/ProjectEvaluation/testwinforms.metadata.v5.1 b/example/winform/TestWinForms/.vs/ProjectEvaluation/testwinforms.metadata.v5.1 index 6c3065cf1b806627cc5e59ed6ba6df2c2c9e492b..b46ac873ed9c8ae3ea13b9b87f32261ee89ca645 100644 Binary files a/example/winform/TestWinForms/.vs/ProjectEvaluation/testwinforms.metadata.v5.1 and b/example/winform/TestWinForms/.vs/ProjectEvaluation/testwinforms.metadata.v5.1 differ diff --git a/example/winform/TestWinForms/.vs/ProjectEvaluation/testwinforms.projects.v5.1 b/example/winform/TestWinForms/.vs/ProjectEvaluation/testwinforms.projects.v5.1 index cb40908093dd9a07c6791861d5190523a2cafb8e..61959b023b72ed8c2fa0c38d584a5a45f84ddb1d 100644 Binary files a/example/winform/TestWinForms/.vs/ProjectEvaluation/testwinforms.projects.v5.1 and b/example/winform/TestWinForms/.vs/ProjectEvaluation/testwinforms.projects.v5.1 differ diff --git a/example/winform/TestWinForms/Form1.Designer.cs b/example/winform/TestWinForms/Form1.Designer.cs new file mode 100644 index 0000000000000000000000000000000000000000..5915d4b7e3adfadde2f5ca1149c85214c829d4cb --- /dev/null +++ b/example/winform/TestWinForms/Form1.Designer.cs @@ -0,0 +1,99 @@ +namespace TestWinForms +{ + partial class Form1 + { + /// + /// 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.button1 = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.button2 = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // button1 + // + this.button1.Location = new System.Drawing.Point(140, 287); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(94, 29); + this.button1.TabIndex = 0; + this.button1.Text = "版本测试"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(87, 117); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(88, 20); + this.label1.TabIndex = 1; + this.label1.Text = "当前版本是:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(181, 117); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(53, 20); + this.label2.TabIndex = 2; + this.label2.Text = "label2"; + // + // button2 + // + this.button2.Location = new System.Drawing.Point(309, 287); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(94, 29); + this.button2.TabIndex = 3; + this.button2.Text = "新增的按钮"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click_1); + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(924, 478); + this.Controls.Add(this.button2); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.Controls.Add(this.button1); + this.Name = "Form1"; + this.Text = "Form1"; + this.Load += new System.EventHandler(this.Form1_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private Button button1; + private Label label1; + private Label label2; + private Button button2; + } +} \ No newline at end of file diff --git a/example/winform/TestWinForms/Form1.cs b/example/winform/TestWinForms/Form1.cs new file mode 100644 index 0000000000000000000000000000000000000000..a3ecad42b46aa7212833f8bdc99556da04c9cfa4 --- /dev/null +++ b/example/winform/TestWinForms/Form1.cs @@ -0,0 +1,106 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Security.AccessControl; +using System.Text; +using GeneralUpdate.ClientCore; +using GeneralUpdate.Core.Bootstrap; +using GeneralUpdate.Core.Domain.Entity; +using GeneralUpdate.Core.Domain.Enum; +using GeneralUpdate.Core.Strategys.PlatformWindows; + +namespace TestWinForms +{ + public partial class Form1 : Form + { + public Form1() + { + InitializeComponent(); + } + + private void Form1_Load(object sender, EventArgs e) + { + //֮ǰDemoһЩص,֮дwinform, ¿ͻ˵,ҵĿͻ˻,Բһ + Upgrade(); + } + + private string mainAppName = "TestWinForms"; + public void Upgrade() + { + var version = GetDllVersion(AppDomain.CurrentDomain.BaseDirectory + $@"{mainAppName}.dll"); + this.label2.Text = version; + + //첽,Ӱ + Task.Run(async () => + { + //öͻ֮佻õĶ + var config = new Configinfo(); + //Ŀͻ˳Ӧõַ + config.InstallPath = AppDomain.CurrentDomain.BaseDirectory; + + //³ĵǰ汾,Ҫ,ֱд + config.ClientVersion = "1.0.0.0"; + //ͻͣ1.ͻ 2. + config.AppType = AppType.ClientApp; + //ָӦԿֿͻӦ Ҫfileserverеһ + config.AppSecretKey = "B8A7FADD-386C-46B0-B283-C9F963420C7C"; + + var updateHost = "http://127.0.0.1:5008/api/update"; + //°صַ Ǽ³url + config.UpdateUrl = $"{updateHost}/Versions/{AppType.UpgradeApp}/{config.ClientVersion}/{config.AppSecretKey}"; + //³exe + config.AppName = "GeneralUpdate.Upgrad"; + //ͻexe + config.MainAppName = mainAppName; + //汾Ϣ ͨǰ򼯻ȡ ÿҪ汾ʱ,һwinformij򼯰汾žͿ,apiԶжǷҪ + var mainVersion = GetDllVersion(AppDomain.CurrentDomain.BaseDirectory + $@"{mainAppName}.dll"); + //¹ҳ + config.UpdateLogUrl = $"{updateHost}/UpdateLog.html"; + //url + config.MainUpdateUrl = $"{updateHost}/Versions/{AppType.ClientApp}/{mainVersion}/{config.AppSecretKey}"; + + // + var generalClientBootstrap = new GeneralClientBootstrap(); + + generalClientBootstrap.Config(config).Option(UpdateOption.DownloadTimeOut, 60).Option(UpdateOption.Encoding, Encoding.Default).Option(UpdateOption.Format, Format.ZIP). + //עһfuncûǷθ£ǿƸЧ + SetCustomOption(() => false).Strategy(); + await generalClientBootstrap.LaunchTaskAsync(); + }); + } + + /// + /// ȡӦ·dllİ汾 + /// + /// + /// + /// + public string GetDllVersion(string filePath) + { + try + { + var fileInfo = new FileInfo(filePath); + if (fileInfo != null && fileInfo.Exists) + { + return Assembly.LoadFrom(filePath).GetName().Version.ToString(); + } + + throw new Exception($"{filePath}ļ汾ȡʧ"); + } + catch (Exception ex) + { + throw new Exception($"{filePath}ļ汾ȡʧ,Ϣ : {ex.Message} .", ex.InnerException); + } + } + + private void button1_Click(object sender, EventArgs e) + { + Upgrade(); + } + + + private void button2_Click_1(object sender, EventArgs e) + { + MessageBox.Show("³ɹ"); + } + } +} \ No newline at end of file diff --git a/example/winform/TestWinForms/Program.cs b/example/winform/TestWinForms/Program.cs new file mode 100644 index 0000000000000000000000000000000000000000..3a9f113f2e8ce02379f3576840441c0563bdf47b --- /dev/null +++ b/example/winform/TestWinForms/Program.cs @@ -0,0 +1,17 @@ +namespace TestWinForms +{ + internal static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + // To customize application configuration such as set high DPI settings or default font, + // see https://aka.ms/applicationconfiguration. + ApplicationConfiguration.Initialize(); + Application.Run(new Form1()); + } + } +} \ No newline at end of file diff --git a/example/winform/TestWinForms/TestWinForms.csproj.user b/example/winform/TestWinForms/TestWinForms.csproj.user new file mode 100644 index 0000000000000000000000000000000000000000..7814ea24efb1226638b58bbf50f1769939812f37 --- /dev/null +++ b/example/winform/TestWinForms/TestWinForms.csproj.user @@ -0,0 +1,8 @@ + + + + + Form + + + diff --git a/example/winform/TestWinForms/TestWinForms.sln b/example/winform/TestWinForms/TestWinForms.sln new file mode 100644 index 0000000000000000000000000000000000000000..2bd7254a082f55800f34fb6e24dd935ee0d09e4a --- /dev/null +++ b/example/winform/TestWinForms/TestWinForms.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.3.32929.385 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestWinForms", "TestWinForms.csproj", "{1E687C9A-CF89-4EC2-88D1-5F6ED35F5549}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeneralUpdate.ClientCore", "..\..\..\src\c#\GeneralUpdate.ClientCore\GeneralUpdate.ClientCore.csproj", "{7806BDFE-9F7B-40FF-87E4-A90F3F49F212}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeneralUpdate.Upgrad", "..\..\..\src\c#\GeneralUpdate.Upgrad\GeneralUpdate.Upgrad.csproj", "{FDEEEA9F-946D-4E2B-857C-279B8FA66231}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1E687C9A-CF89-4EC2-88D1-5F6ED35F5549}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1E687C9A-CF89-4EC2-88D1-5F6ED35F5549}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1E687C9A-CF89-4EC2-88D1-5F6ED35F5549}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1E687C9A-CF89-4EC2-88D1-5F6ED35F5549}.Release|Any CPU.Build.0 = Release|Any CPU + {7806BDFE-9F7B-40FF-87E4-A90F3F49F212}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7806BDFE-9F7B-40FF-87E4-A90F3F49F212}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7806BDFE-9F7B-40FF-87E4-A90F3F49F212}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7806BDFE-9F7B-40FF-87E4-A90F3F49F212}.Release|Any CPU.Build.0 = Release|Any CPU + {FDEEEA9F-946D-4E2B-857C-279B8FA66231}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FDEEEA9F-946D-4E2B-857C-279B8FA66231}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FDEEEA9F-946D-4E2B-857C-279B8FA66231}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FDEEEA9F-946D-4E2B-857C-279B8FA66231}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {7010610C-F3F1-4A06-B67D-95049FD4C3E7} + EndGlobalSection +EndGlobal diff --git a/example/winform/readme.md b/example/winform/readme.md index e49b54672c145a226477b5062a62a1310cdf900b..f6778e771734fcd054425baa92c519581e03e287 100644 --- a/example/winform/readme.md +++ b/example/winform/readme.md @@ -1,12 +1,13 @@ 使用方法 1. 先运行example\fileserver 这个文件服务器,这个服务器中整合了版本更新查询和文件下载功能。具体代码逻辑可以参看官网的介绍,这里就不赘述了,为了方便测试,把官网的api服务加上文件下载弄在了一起,在demo中,默认配置的是1.0.0.9的可用升级版本。 -2. 打开TestWinForms.csproj项目.在Load方法中会先去请求文件服务器,检查是否需要更新版本,如果需要更新,就会启动Upgrade.exe程序来更新,并且关闭winform程序,更新完后会自动重启 +2. 打开TestWinForms.sln项目.在Load方法中会先去请求文件服务器,检查是否需要更新版本,如果需要更新,就会启动Upgrade.exe程序来更新,并且关闭winform程序,更新完后会自动重启 3.运行升级之前需要把GeneralUpdate.Upgrad程序中bin目录下面的所有文件复制到run文件夹(见下面的文件夹解释)中才能正常更新。demo中是直接引用source的源码的,后面发布了也可以引用nuget包。 4.代码里有比较详细的注释,可以试着操作一下 +5.如果项目中GeneralUpdate.ClientCore,GeneralUpdate.Upgrad说找不到,直接引用src中C#模块的对应代码过来,尤其是Upgrad是必须要的,要把bin里面的复制到运行文件夹才行 直接看效果 如果想直接看效果,可以直接打开example\winform\测试包 这个文件夹,将"可用版本.zip"解压。运行文件服务器,再运行解压后的run文件夹中的TestWinForms.exe,就能先体验一下更新的过程。