using AIK.Common.Interface; using AIK.Common.Models; using AIK.Common.SysCommon; using AIK.Service.IService; using AIK.Views.UpdatePages; using AutoUpdaterDotNET; using HidSharp.Utility; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Http; using System.Reflection; using System.Security; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Xml; namespace AIKKey.Infrastructure { public class UpdateService : IUpdateService { private readonly IAikDataService _aikDataService; public UpdateService(IAikDataService aikDataService) { _aikDataService = aikDataService; } public async Task CheckForUpdateAsync() { try { // 1. 获取当前版本 var currentVersionStr = Assembly.GetEntryAssembly()? .GetName().Version?.ToString(); var currentShortVersionStr = ToShortVersionString(Version.Parse(currentVersionStr)); var currentVersion = Version.Parse(currentShortVersionStr); var updateinfo = await _aikDataService.GetAppVersionInfo(WebApiAddress.PCZipType); if (updateinfo == null) return new UpdateProgressDto { IsAvailable = false, CurrentVersion = currentShortVersionStr, LatestVersion = string.Empty, Status = "获取服务器版本数据失败", HasError = true, DownloadUrl = string.Empty // 可选:传递下载地址 }; ; var versionName = updateinfo.VersionName; // e.g. "v1.2.8" var fileUrl = updateinfo.FileUrl; var force = updateinfo.Force; var versionCode = int.Parse(updateinfo.VersionCode.Replace(".", "")); // 用于比较 // 移除 "v" 前缀并确保是合法 Version var cleanVersionStr = updateinfo.VersionCode?.TrimStart('v', 'V') ?? "1.0.0"; if (!Version.TryParse(cleanVersionStr, out var latestVersion)) latestVersion = new Version(versionCode, 0, 0); // fallback to versionCode bool isUpdateAvailable = latestVersion > currentVersion; return new UpdateProgressDto { IsAvailable = isUpdateAvailable, CurrentVersion = currentShortVersionStr, LatestVersion = latestVersion.ToString(), Status = updateinfo.VersionContent, HasError = false, DownloadUrl = updateinfo.FileUrl // 可选:传递下载地址 }; } catch (Exception ex) { return new UpdateProgressDto { IsAvailable = false, Status = "Failed to check for updates", HasError = true, ErrorMessage = ex.Message }; } } private string ToShortVersionString(Version version) { if (version == null) return "0.0"; string v = version.ToString(); // 移除尾部的 ".0",但至少保留 x.x while (v.EndsWith(".0") && v.Count(c => c == '.') > 1) { v = v.Substring(0, v.LastIndexOf('.')); } return v; } /// /// 启动 AutoUpdater 的完整更新流程(使用同一个 XML) /// public async Task StartUpdateProcess() { // 1. 先获取最新版本信息 var updateInfo = await CheckForUpdateAsync(); if (!updateInfo.IsAvailable) return; // 2. 构造 AutoUpdater.NET 能识别的 XML string xmlContent = $@" {SecurityElement.Escape(updateInfo.LatestVersion)} {SecurityElement.Escape(updateInfo.DownloadUrl)} false "; // 创建临时 XML 文件 string tempXmlPath = Path.Combine(Path.GetTempPath(), "AIK_Update_Info.xml"); File.WriteAllText(tempXmlPath, xmlContent, Encoding.UTF8); AutoUpdaterDotNET.AutoUpdater.AppTitle = "AIKKey"; AutoUpdaterDotNET.AutoUpdater.Mandatory = false; AutoUpdaterDotNET.AutoUpdater.ShowSkipButton = false; AutoUpdaterDotNET.AutoUpdater.ShowRemindLaterButton = false; AutoUpdaterDotNET.AutoUpdater.OpenDownloadPage = false; AutoUpdaterDotNET.AutoUpdater.ReportErrors = true; string fileUri = new Uri(tempXmlPath).AbsoluteUri; // 使用相同的 XML URL AutoUpdaterDotNET.AutoUpdater.Start(fileUri); } public async Task GetUpdateInfoAsync() { try { var currentVersionStr = Assembly.GetEntryAssembly()?.GetName().Version?.ToString(); var currentShortVersionStr = ToShortVersionString(Version.Parse(currentVersionStr)); var currentVersion = Version.Parse(currentShortVersionStr); var updateinfo = await _aikDataService.GetAppVersionInfo(WebApiAddress.PCZipType); if (updateinfo == null) return new UpdateInfoResult { IsUpdateAvailable = false }; var cleanVersionStr = updateinfo.VersionCode?.TrimStart('v', 'V') ?? "1.0.0"; if (!Version.TryParse(cleanVersionStr, out var latestVersion)) latestVersion = new Version(1, 0, 0); bool isUpdateAvailable = latestVersion > currentVersion; return new UpdateInfoResult { VersionEnContent = updateinfo.VersionEnContent ?? "", VersionContent = updateinfo.VersionContent ?? "", IsUpdateAvailable = isUpdateAvailable, LatestVersion = latestVersion.ToString(), CurrentVersion = currentShortVersionStr, DownloadUrl = updateinfo.FileUrl, ChangeLog = updateinfo.VersionContent ?? "", IsMandatory = updateinfo.Force // 假设 Force 字段代表强制更新 }; } catch (Exception) { return new UpdateInfoResult { IsUpdateAvailable = false }; } } public async Task CheckForUpdate() { var result = await GetUpdateInfoAsync(); if (result.IsUpdateAvailable) { // 构造 AutoUpdater.NET 能识别的 XML string xmlContent = $@" {SecurityElement.Escape(result.LatestVersion)} {SecurityElement.Escape(result.DownloadUrl)} true "; // 创建临时 XML 文件 string tempXmlPath = Path.Combine(Path.GetTempPath(), "AIK_Update_Info.xml"); File.WriteAllText(tempXmlPath, xmlContent, Encoding.UTF8); AutoUpdaterDotNET.AutoUpdater.AppTitle = "AIKKey"; AutoUpdaterDotNET.AutoUpdater.Mandatory = true; AutoUpdater.UpdateMode = Mode.ForcedDownload; AutoUpdaterDotNET.AutoUpdater.ShowSkipButton = false; AutoUpdaterDotNET.AutoUpdater.ShowRemindLaterButton = false; AutoUpdaterDotNET.AutoUpdater.OpenDownloadPage = false; AutoUpdaterDotNET.AutoUpdater.ReportErrors = true; string fileUri = new Uri(tempXmlPath).AbsoluteUri; if (result.IsMandatory) { AutoUpdaterDotNET.AutoUpdater.Start(fileUri); return; // 强制更新,直接返回 } // 显示你的自定义窗口 var customDialog = new UpdateWindow(result.LatestVersion, result.CurrentVersion,result.VersionContent,result.VersionEnContent); var dialogResult = customDialog.ShowDialog(); // 根据用户在自定义窗口的选择决定是否开始更新 if (dialogResult == true) // 用户点击了“立即更新” { // 使用相同的 XML URL AutoUpdaterDotNET.AutoUpdater.Start(fileUri); } } else { //MessageBox.Show("当前已是最新版本"); } } } }