diff --git a/Ink Canvas/Helpers/AutoUpdateHelper.cs b/Ink Canvas/Helpers/AutoUpdateHelper.cs index acf21f04..b2c65aa7 100644 --- a/Ink Canvas/Helpers/AutoUpdateHelper.cs +++ b/Ink Canvas/Helpers/AutoUpdateHelper.cs @@ -105,12 +105,18 @@ namespace Ink_Canvas.Helpers return -1; } - // 检测线路组延迟,返回最快组 + // 检测线路组延迟,返回最快组(保持向后兼容) private static async Task GetFastestLineGroup(UpdateChannel channel) + { + var availableGroups = await GetAvailableLineGroupsOrdered(channel); + return availableGroups.Count > 0 ? availableGroups[0] : null; + } + + // 获取所有可用线路组,按延迟排序 + public static async Task> GetAvailableLineGroupsOrdered(UpdateChannel channel) { var groups = ChannelLineGroups[channel]; - long minDelay = long.MaxValue; - UpdateLineGroup bestGroup = null; + var availableGroups = new List<(UpdateLineGroup group, long delay)>(); LogHelper.WriteLogToFile($"AutoUpdate | 开始检测通道 {channel} 下所有线路组延迟..."); @@ -121,11 +127,7 @@ namespace Ink_Canvas.Helpers if (delay >= 0) { LogHelper.WriteLogToFile($"AutoUpdate | 线路组 {group.GroupName} 延迟: {delay}ms"); - if (delay < minDelay) - { - minDelay = delay; - bestGroup = group; - } + availableGroups.Add((group, delay)); } else { @@ -133,16 +135,26 @@ namespace Ink_Canvas.Helpers } } - if (bestGroup != null) + // 按延迟排序,延迟最小的排在前面 + var orderedGroups = availableGroups + .OrderBy(x => x.delay) + .Select(x => x.group) + .ToList(); + + if (orderedGroups.Count > 0) { - LogHelper.WriteLogToFile($"AutoUpdate | 选择最快线路组: {bestGroup.GroupName} (延迟: {minDelay}ms)"); + LogHelper.WriteLogToFile($"AutoUpdate | 找到 {orderedGroups.Count} 个可用线路组,按延迟排序:"); + for (int i = 0; i < orderedGroups.Count; i++) + { + LogHelper.WriteLogToFile($"AutoUpdate | {i + 1}. {orderedGroups[i].GroupName}"); + } } else { LogHelper.WriteLogToFile("AutoUpdate | 所有线路组均不可用", LogHelper.LogType.Error); } - return bestGroup; + return orderedGroups; } // 获取远程版本号 @@ -218,7 +230,7 @@ namespace Ink_Canvas.Helpers } } - // 主要的更新检测方法(优先检测延迟) + // 主要的更新检测方法(优先检测延迟,失败时自动切换线路组) public static async Task<(string remoteVersion, UpdateLineGroup lineGroup)> CheckForUpdates(UpdateChannel channel = UpdateChannel.Release, bool alwaysGetRemote = false) { try @@ -227,39 +239,45 @@ namespace Ink_Canvas.Helpers LogHelper.WriteLogToFile($"AutoUpdate | 本地版本: {localVersion}"); LogHelper.WriteLogToFile($"AutoUpdate | 检测通道 {channel} 下最快线路组..."); - // 优先检测延迟,选择最快线路组 - var bestGroup = await GetFastestLineGroup(channel); - if (bestGroup == null) + // 获取所有可用线路组(按延迟排序) + var availableGroups = await GetAvailableLineGroupsOrdered(channel); + if (availableGroups.Count == 0) { LogHelper.WriteLogToFile("AutoUpdate | 所有线路组均不可用", LogHelper.LogType.Error); return (null, null); } - LogHelper.WriteLogToFile($"AutoUpdate | 使用最快线路组获取版本信息: {bestGroup.GroupName}"); - string remoteVersion = await GetRemoteVersion(bestGroup.VersionUrl); - - if (remoteVersion != null) + // 依次尝试每个线路组,直到成功获取版本信息 + foreach (var group in availableGroups) { - LogHelper.WriteLogToFile($"AutoUpdate | 远程版本: {remoteVersion}"); - Version local = new Version(localVersion); - Version remote = new Version(remoteVersion); + LogHelper.WriteLogToFile($"AutoUpdate | 尝试使用线路组获取版本信息: {group.GroupName}"); + string remoteVersion = await GetRemoteVersion(group.VersionUrl); - if (remote > local || alwaysGetRemote) + if (remoteVersion != null) { - LogHelper.WriteLogToFile($"AutoUpdate | 发现新版本或强制获取: {remoteVersion}"); - return (remoteVersion, bestGroup); + LogHelper.WriteLogToFile($"AutoUpdate | 成功从线路组 {group.GroupName} 获取远程版本: {remoteVersion}"); + Version local = new Version(localVersion); + Version remote = new Version(remoteVersion); + + if (remote > local || alwaysGetRemote) + { + LogHelper.WriteLogToFile($"AutoUpdate | 发现新版本或强制获取: {remoteVersion}"); + return (remoteVersion, group); + } + else + { + LogHelper.WriteLogToFile($"AutoUpdate | 当前版本已是最新"); + return (null, group); + } } else { - LogHelper.WriteLogToFile($"AutoUpdate | 当前版本已是最新"); - return (null, bestGroup); + LogHelper.WriteLogToFile($"AutoUpdate | 线路组 {group.GroupName} 获取版本失败,尝试下一个线路组", LogHelper.LogType.Warning); } } - else - { - LogHelper.WriteLogToFile("AutoUpdate | 获取远程版本失败", LogHelper.LogType.Error); - return (null, bestGroup); - } + + LogHelper.WriteLogToFile("AutoUpdate | 所有线路组均无法获取版本信息", LogHelper.LogType.Error); + return (null, null); } catch (Exception ex) { @@ -270,6 +288,12 @@ namespace Ink_Canvas.Helpers // 使用指定线路组下载新版 public static async Task DownloadSetupFile(string version, UpdateLineGroup group) + { + return await DownloadSetupFileWithFallback(version, new List { group }); + } + + // 使用多线路组下载新版(支持自动切换) + public static async Task DownloadSetupFileWithFallback(string version, List groups) { try { @@ -288,26 +312,33 @@ namespace Ink_Canvas.Helpers LogHelper.WriteLogToFile($"AutoUpdate | 创建更新目录: {updatesFolderPath}"); } - string url = string.Format(group.DownloadUrlFormat, version); string zipFilePath = Path.Combine(updatesFolderPath, $"InkCanvasForClass.CE.{version}.zip"); - - LogHelper.WriteLogToFile($"AutoUpdate | 从线路组 {group.GroupName} 下载: {url}"); LogHelper.WriteLogToFile($"AutoUpdate | 目标文件路径: {zipFilePath}"); SaveDownloadStatus(false); - bool downloadSuccess = await DownloadFile(url, zipFilePath); + + // 依次尝试每个线路组 + foreach (var group in groups) + { + string url = string.Format(group.DownloadUrlFormat, version); + LogHelper.WriteLogToFile($"AutoUpdate | 尝试从线路组 {group.GroupName} 下载: {url}"); + + bool downloadSuccess = await DownloadFile(url, zipFilePath); + + if (downloadSuccess) + { + SaveDownloadStatus(true); + LogHelper.WriteLogToFile($"AutoUpdate | 从线路组 {group.GroupName} 下载成功"); + return true; + } + else + { + LogHelper.WriteLogToFile($"AutoUpdate | 线路组 {group.GroupName} 下载失败,尝试下一个线路组", LogHelper.LogType.Warning); + } + } - if (downloadSuccess) - { - SaveDownloadStatus(true); - LogHelper.WriteLogToFile("AutoUpdate | 安装包下载成功"); - return true; - } - else - { - LogHelper.WriteLogToFile("AutoUpdate | 下载失败", LogHelper.LogType.Error); - return false; - } + LogHelper.WriteLogToFile("AutoUpdate | 所有线路组下载均失败", LogHelper.LogType.Error); + return false; } catch (Exception ex) { diff --git a/Ink Canvas/MainWindow.xaml.cs b/Ink Canvas/MainWindow.xaml.cs index 2f2e6cd2..6cdf9da0 100644 --- a/Ink Canvas/MainWindow.xaml.cs +++ b/Ink Canvas/MainWindow.xaml.cs @@ -425,7 +425,42 @@ namespace Ink_Canvas { } } + // 辅助方法:使用多线路组下载更新 + private async Task DownloadUpdateWithFallback(string version, AutoUpdateHelper.UpdateLineGroup primaryGroup, UpdateChannel channel) + { + try + { + // 如果主要线路组可用,直接使用 + if (primaryGroup != null) + { + LogHelper.WriteLogToFile($"AutoUpdate | 使用主要线路组下载: {primaryGroup.GroupName}"); + return await AutoUpdateHelper.DownloadSetupFile(version, primaryGroup); + } + + // 如果主要线路组不可用,获取所有可用线路组 + LogHelper.WriteLogToFile("AutoUpdate | 主要线路组不可用,获取所有可用线路组"); + var availableGroups = await AutoUpdateHelper.GetAvailableLineGroupsOrdered(channel); + if (availableGroups.Count == 0) + { + LogHelper.WriteLogToFile("AutoUpdate | 没有可用的线路组", LogHelper.LogType.Error); + return false; + } + + LogHelper.WriteLogToFile($"AutoUpdate | 使用 {availableGroups.Count} 个可用线路组进行下载"); + return await AutoUpdateHelper.DownloadSetupFileWithFallback(version, availableGroups); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"AutoUpdate | 下载更新时出错: {ex.Message}", LogHelper.LogType.Error); + return false; + } + } + private async void AutoUpdate() { + // 清除之前的更新状态,确保使用新通道重新检查 + AvailableLatestVersion = null; + AvailableLatestLineGroup = null; + // 使用当前选择的更新通道检查更新 var (remoteVersion, lineGroup) = await AutoUpdateHelper.CheckForUpdates(Settings.Startup.UpdateChannel); AvailableLatestVersion = remoteVersion; @@ -461,15 +496,8 @@ namespace Ink_Canvas { if (Settings.Startup.IsAutoUpdateWithSilence) { LogHelper.WriteLogToFile("AutoUpdate | Silent update enabled, downloading update automatically without notification"); - // 静默下载更新,传递当前选择的更新通道 - if (AvailableLatestLineGroup != null) - isDownloadSuccessful = await AutoUpdateHelper.DownloadSetupFile(AvailableLatestVersion, AvailableLatestLineGroup); - else - { - var (_, lineGroup2) = await AutoUpdateHelper.CheckForUpdates(Settings.Startup.UpdateChannel, true); - if (lineGroup2 != null) - isDownloadSuccessful = await AutoUpdateHelper.DownloadSetupFile(AvailableLatestVersion, lineGroup2); - } + // 静默下载更新,使用多线路组下载功能 + isDownloadSuccessful = await DownloadUpdateWithFallback(AvailableLatestVersion, AvailableLatestLineGroup, Settings.Startup.UpdateChannel); if (isDownloadSuccessful) { LogHelper.WriteLogToFile("AutoUpdate | Update downloaded successfully, will install when conditions are met"); @@ -518,15 +546,8 @@ namespace Ink_Canvas { // 显示下载进度提示 MessageBox.Show("开始下载更新,请稍候...", "正在更新", MessageBoxButton.OK, MessageBoxImage.Information); - // 下载更新文件,传递当前选择的更新通道 - if (AvailableLatestLineGroup != null) - isDownloadSuccessful = await AutoUpdateHelper.DownloadSetupFile(AvailableLatestVersion, AvailableLatestLineGroup); - else - { - var (_, lineGroup2) = await AutoUpdateHelper.CheckForUpdates(Settings.Startup.UpdateChannel, true); - if (lineGroup2 != null) - isDownloadSuccessful = await AutoUpdateHelper.DownloadSetupFile(AvailableLatestVersion, lineGroup2); - } + // 下载更新文件,使用多线路组下载功能 + isDownloadSuccessful = await DownloadUpdateWithFallback(AvailableLatestVersion, AvailableLatestLineGroup, Settings.Startup.UpdateChannel); if (isDownloadSuccessful) { // 下载成功,提示用户准备安装 @@ -555,15 +576,8 @@ namespace Ink_Canvas { // 稍后更新:静默下载,在软件关闭时自动安装 LogHelper.WriteLogToFile("AutoUpdate | User chose to update later"); - // 不管设置如何,都进行下载 - if (AvailableLatestLineGroup != null) - isDownloadSuccessful = await AutoUpdateHelper.DownloadSetupFile(AvailableLatestVersion, AvailableLatestLineGroup); - else - { - var (_, lineGroup2) = await AutoUpdateHelper.CheckForUpdates(Settings.Startup.UpdateChannel, true); - if (lineGroup2 != null) - isDownloadSuccessful = await AutoUpdateHelper.DownloadSetupFile(AvailableLatestVersion, lineGroup2); - } + // 不管设置如何,都进行下载,使用多线路组下载功能 + isDownloadSuccessful = await DownloadUpdateWithFallback(AvailableLatestVersion, AvailableLatestLineGroup, Settings.Startup.UpdateChannel); if (isDownloadSuccessful) { LogHelper.WriteLogToFile("AutoUpdate | Update downloaded successfully, will install when application closes"); diff --git a/Ink Canvas/MainWindow_cs/MW_Settings.cs b/Ink Canvas/MainWindow_cs/MW_Settings.cs index c18001fc..81084903 100644 --- a/Ink Canvas/MainWindow_cs/MW_Settings.cs +++ b/Ink Canvas/MainWindow_cs/MW_Settings.cs @@ -1992,14 +1992,42 @@ namespace Ink_Canvas { HideSubPanels(); } - private void UpdateChannelSelector_Checked(object sender, RoutedEventArgs e) { + private async void UpdateChannelSelector_Checked(object sender, RoutedEventArgs e) { if (!isLoaded) return; var radioButton = sender as System.Windows.Controls.RadioButton; if (radioButton != null) { string channel = radioButton.Tag.ToString(); - Settings.Startup.UpdateChannel = channel == "Beta" ? UpdateChannel.Beta : UpdateChannel.Release; + UpdateChannel newChannel = channel == "Beta" ? UpdateChannel.Beta : UpdateChannel.Release; + + // 如果通道没有变化,不需要执行更新检查 + if (Settings.Startup.UpdateChannel == newChannel) { + return; + } + + Settings.Startup.UpdateChannel = newChannel; LogHelper.WriteLogToFile($"Settings | Update channel changed to {Settings.Startup.UpdateChannel}"); SaveSettingsToFile(); + + // 如果启用了自动更新,立即执行完整的检查更新操作 + if (Settings.Startup.IsAutoUpdate) { + LogHelper.WriteLogToFile($"AutoUpdate | Channel changed to {newChannel}, performing immediate update check"); + + // 执行完整的更新检查 + await Task.Run(async () => { + try { + // 调用主窗口的AutoUpdate方法,它会自动清除之前的更新状态并使用新通道重新检查 + Dispatcher.Invoke(() => { + AutoUpdate(); + }); + } + catch (Exception ex) { + LogHelper.WriteLogToFile($"AutoUpdate | Error during channel switch update check: {ex.Message}", LogHelper.LogType.Error); + } + }); + } + else { + LogHelper.WriteLogToFile($"AutoUpdate | Channel changed to {newChannel}, but auto-update is disabled"); + } } } diff --git a/Ink Canvas/MainWindow_cs/MW_Timer.cs b/Ink Canvas/MainWindow_cs/MW_Timer.cs index 5c7d4a8c..486291aa 100644 --- a/Ink Canvas/MainWindow_cs/MW_Timer.cs +++ b/Ink Canvas/MainWindow_cs/MW_Timer.cs @@ -329,17 +329,36 @@ namespace Ink_Canvas { if (!File.Exists(statusFilePath) || File.ReadAllText(statusFilePath).Trim().ToLower() != "true") { LogHelper.WriteLogToFile("AutoUpdate | Update file not downloaded yet"); - // 尝试下载更新文件 + // 尝试下载更新文件,使用多线路组下载功能 Task.Run(async () => { bool isDownloadSuccessful = false; - if (AvailableLatestLineGroup != null) - isDownloadSuccessful = await AutoUpdateHelper.DownloadSetupFile(AvailableLatestVersion, AvailableLatestLineGroup); - else + + try { - var (_, lineGroup2) = await AutoUpdateHelper.CheckForUpdates(Settings.Startup.UpdateChannel, true); - if (lineGroup2 != null) - isDownloadSuccessful = await AutoUpdateHelper.DownloadSetupFile(AvailableLatestVersion, lineGroup2); + // 如果主要线路组可用,直接使用 + if (AvailableLatestLineGroup != null) + { + LogHelper.WriteLogToFile($"AutoUpdate | 使用主要线路组下载: {AvailableLatestLineGroup.GroupName}"); + isDownloadSuccessful = await AutoUpdateHelper.DownloadSetupFile(AvailableLatestVersion, AvailableLatestLineGroup); + } + + // 如果主要线路组不可用或下载失败,获取所有可用线路组 + if (!isDownloadSuccessful) + { + LogHelper.WriteLogToFile("AutoUpdate | 主要线路组不可用或下载失败,获取所有可用线路组"); + var availableGroups = await AutoUpdateHelper.GetAvailableLineGroupsOrdered(Settings.Startup.UpdateChannel); + if (availableGroups.Count > 0) + { + LogHelper.WriteLogToFile($"AutoUpdate | 使用 {availableGroups.Count} 个可用线路组进行下载"); + isDownloadSuccessful = await AutoUpdateHelper.DownloadSetupFileWithFallback(AvailableLatestVersion, availableGroups); + } + } } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"AutoUpdate | 下载更新时出错: {ex.Message}", LogHelper.LogType.Error); + } + if (isDownloadSuccessful) { LogHelper.WriteLogToFile("AutoUpdate | Update downloaded successfully, will check again for installation"); // 重新启动计时器,下次检查时安装