| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- using System.Reflection;
- using Serilog;
- namespace YZWater.Core.Services;
- /// <summary>
- /// 在线升级服务(借鉴 AutoFMA UpdateService,委托注入模式)
- ///
- /// 设计原则:
- /// 1. Core 层只负责版本管理和更新触发,不依赖具体 UI 框架
- /// 2. 实际的更新检查/下载/安装逻辑由 UI 层通过 SetTriggerAction 注入
- /// 3. config.json 配置 Update.Enabled / CheckOnStartup / CheckIntervalHours
- ///
- /// Avalonia 无 AutoUpdater.NET 官方支持,UI 层可接入 Squirrel 或自研下载器后注入。
- /// </summary>
- public static class UpdateService
- {
- private static DateTime? _lastCheckTime;
- private static Action? _triggerAction;
- private static System.Threading.Timer? _checkTimer;
- /// <summary>
- /// 更新配置
- /// </summary>
- public class UpdateConfig
- {
- /// <summary>是否启用在线更新</summary>
- public bool Enabled { get; set; }
- /// <summary>更新清单地址(appcast URL)</summary>
- public string AppcastUrl { get; set; } = string.Empty;
- /// <summary>启动时是否检查更新</summary>
- public bool CheckOnStartup { get; set; } = true;
- /// <summary>检查间隔(小时,默认 24)</summary>
- public int CheckIntervalHours { get; set; } = 24;
- }
- /// <summary>
- /// 当前程序版本(Major.Minor.Build)
- /// </summary>
- public static string GetCurrentVersion()
- {
- var version = Assembly.GetEntryAssembly()?.GetName().Version;
- return version != null ? $"{version.Major}.{version.Minor}.{version.Build}" : "0.0.0";
- }
- /// <summary>上次检查时间</summary>
- public static DateTime? LastCheckTime => _lastCheckTime;
- /// <summary>更新触发器是否已注入</summary>
- public static bool IsTriggerRegistered => _triggerAction != null;
- /// <summary>
- /// 注入实际更新触发逻辑(由 UI 层调用,如 Squirrel 下载安装流程)
- /// </summary>
- public static void SetTriggerAction(Action triggerAction)
- {
- _triggerAction = triggerAction;
- Log.Information("在线更新触发器已注入");
- }
- /// <summary>
- /// 触发在线更新
- /// </summary>
- public static bool TriggerUpdate()
- {
- if (_triggerAction == null)
- {
- Log.Warning("更新触发器未注入,无法执行在线更新");
- return false;
- }
- Log.Information("触发在线更新,当前版本: {Version}", GetCurrentVersion());
- _lastCheckTime = DateTime.Now;
- try
- {
- _triggerAction();
- return true;
- }
- catch (Exception ex)
- {
- Log.Error(ex, "触发在线更新失败");
- return false;
- }
- }
- /// <summary>
- /// 启动定期检查(启动时检查一次 + 按 CheckIntervalHours 定时)
- /// </summary>
- public static void StartPeriodicCheck(Action onCheckDue)
- {
- var config = ConfigService.GetConfig()?.Update;
- if (config is not { Enabled: true })
- {
- Log.Debug("在线更新未启用,跳过定期检查");
- return;
- }
- var interval = TimeSpan.FromHours(Math.Max(1, config.CheckIntervalHours));
- // 启动时检查一次
- if (config.CheckOnStartup)
- {
- Task.Run(() =>
- {
- try
- {
- _lastCheckTime = DateTime.Now;
- onCheckDue();
- }
- catch (Exception ex)
- {
- Log.Error(ex, "启动时检查更新失败");
- }
- });
- }
- // 定时检查
- _checkTimer ??= new System.Threading.Timer(_ =>
- {
- try
- {
- _lastCheckTime = DateTime.Now;
- onCheckDue();
- }
- catch (Exception ex)
- {
- Log.Error(ex, "定时检查更新失败");
- }
- }, null, interval, interval);
- Log.Information("在线更新定期检查已启动,间隔 {Hours} 小时", config.CheckIntervalHours);
- }
- /// <summary>
- /// 停止定期检查
- /// </summary>
- public static void StopPeriodicCheck()
- {
- _checkTimer?.Dispose();
- _checkTimer = null;
- }
- }
|