improve:自动更新

This commit is contained in:
2026-03-28 20:20:44 +08:00
parent b19c19d73c
commit 1124bb6bfa
7 changed files with 206 additions and 14 deletions
+90 -6
View File
@@ -27,6 +27,87 @@ namespace Ink_Canvas.Helpers
private static readonly string updatesFolderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "AutoUpdate");
private static string statusFilePath;
public static bool IsX64UpdatePackageSelected()
{
try
{
return MainWindow.Settings?.Startup?.UpdatePackageArchitecture == UpdatePackageArchitecture.X64;
}
catch
{
return false;
}
}
private static string NormalizeVersionForUpdate(string version)
{
if (string.IsNullOrWhiteSpace(version)) return version;
return version.Trim().TrimStart('v', 'V');
}
public static string AppendX64SuffixBeforeZipExtension(string url)
{
if (string.IsNullOrEmpty(url) || !IsX64UpdatePackageSelected()) return url;
int query = url.IndexOf('?');
string pathPart = query >= 0 ? url.Substring(0, query) : url;
string qs = query >= 0 ? url.Substring(query) : "";
const string ext = ".zip";
int idx = pathPart.LastIndexOf(ext, StringComparison.OrdinalIgnoreCase);
if (idx < 0) return url;
var basePart = pathPart.Substring(0, idx);
if (basePart.EndsWith("-x64", StringComparison.OrdinalIgnoreCase)) return url;
return basePart + "-x64" + ext + qs;
}
public static string GetUpdateZipFileName(string version)
{
var v = NormalizeVersionForUpdate(version);
return IsX64UpdatePackageSelected()
? $"InkCanvasForClass.CE.{v}-x64.zip"
: $"InkCanvasForClass.CE.{v}.zip";
}
public static string GetUpdateDownloadStatusFilePath(string version)
{
var v = NormalizeVersionForUpdate(version);
string name = IsX64UpdatePackageSelected()
? $"DownloadV{v}_x64Status.txt"
: $"DownloadV{v}Status.txt";
return Path.Combine(updatesFolderPath, name);
}
public static string GetLocalUpdateZipFilePath(string version)
{
return Path.Combine(updatesFolderPath, GetUpdateZipFileName(version));
}
private static string PickBrowserDownloadUrlFromAssets(JToken assets)
{
if (assets == null || !assets.Any()) return null;
bool wantX64 = IsX64UpdatePackageSelected();
string anyZip = null;
string x64Zip = null;
string nonX64Zip = null;
foreach (JToken a in assets)
{
string name = a["name"]?.ToString();
string url = a["browser_download_url"]?.ToString();
if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(url)) continue;
if (!name.EndsWith(".zip", StringComparison.OrdinalIgnoreCase)) continue;
if (anyZip == null) anyZip = url;
if (name.EndsWith("-x64.zip", StringComparison.OrdinalIgnoreCase))
{
if (x64Zip == null) x64Zip = url;
}
else
{
if (nonX64Zip == null) nonX64Zip = url;
}
}
if (wantX64)
return x64Zip ?? anyZip;
return nonX64Zip ?? anyZip;
}
// 线路组结构体(包含版本、下载、日志地址)
public class UpdateLineGroup
@@ -317,6 +398,7 @@ namespace Ink_Canvas.Helpers
if (!string.IsNullOrEmpty(group.DownloadUrlFormat))
{
testUrl = group.DownloadUrlFormat.Replace("{0}", "test");
testUrl = AppendX64SuffixBeforeZipExtension(testUrl);
}
}
catch
@@ -608,7 +690,7 @@ namespace Ink_Canvas.Helpers
if (version == targetVersion || version == $"v{targetVersion}" || version == $"V{targetVersion}")
{
string releaseNotes = release["body"]?.ToString();
string downloadUrl = release["assets"]?.First?["browser_download_url"]?.ToString();
string downloadUrl = PickBrowserDownloadUrlFromAssets(release["assets"]);
// 解析发布时间
DateTime? releaseTime = null;
@@ -649,7 +731,7 @@ namespace Ink_Canvas.Helpers
var latestRelease = releases[0];
string version = latestRelease["tag_name"]?.ToString();
string releaseNotes = latestRelease["body"]?.ToString();
string downloadUrl = latestRelease["assets"]?.First?["browser_download_url"]?.ToString();
string downloadUrl = PickBrowserDownloadUrlFromAssets(latestRelease["assets"]);
DateTime? releaseTime = null;
if (latestRelease["published_at"] != null && DateTime.TryParse(latestRelease["published_at"].ToString(), out DateTime parsedTime))
@@ -675,7 +757,7 @@ namespace Ink_Canvas.Helpers
var json = JObject.Parse(response);
string version = json["tag_name"]?.ToString();
string releaseNotes = json["body"]?.ToString();
string downloadUrl = json["assets"]?.First?["browser_download_url"]?.ToString();
string downloadUrl = PickBrowserDownloadUrlFromAssets(json["assets"]);
DateTime? releaseTime = null;
if (json["published_at"] != null && DateTime.TryParse(json["published_at"].ToString(), out DateTime parsedTime))
@@ -865,7 +947,8 @@ namespace Ink_Canvas.Helpers
{
try
{
statusFilePath = Path.Combine(updatesFolderPath, $"DownloadV{version}Status.txt");
version = NormalizeVersionForUpdate(version);
statusFilePath = GetUpdateDownloadStatusFilePath(version);
if (File.Exists(statusFilePath) && File.ReadAllText(statusFilePath).Trim().ToLower() == "true")
{
@@ -881,7 +964,7 @@ namespace Ink_Canvas.Helpers
LogHelper.WriteLogToFile($"AutoUpdate | 创建更新目录: {updatesFolderPath}");
}
string zipFilePath = Path.Combine(updatesFolderPath, $"InkCanvasForClass.CE.{version}.zip");
string zipFilePath = GetLocalUpdateZipFilePath(version);
LogHelper.WriteLogToFile($"AutoUpdate | 目标文件路径: {zipFilePath}");
SaveDownloadStatus(false);
@@ -899,6 +982,7 @@ namespace Ink_Canvas.Helpers
foreach (var group in groups)
{
string url = string.Format(group.DownloadUrlFormat, version);
url = AppendX64SuffixBeforeZipExtension(url);
// 智教联盟需要先获取真实下载地址
if (group.GroupName == "智教联盟")
{
@@ -2170,7 +2254,7 @@ namespace Ink_Canvas.Helpers
{
string version = item["tag_name"]?.ToString();
string releaseNotes = item["body"]?.ToString();
string downloadUrl = item["assets"]?.First?["browser_download_url"]?.ToString();
string downloadUrl = PickBrowserDownloadUrlFromAssets(item["assets"]);
if (!string.IsNullOrEmpty(version) && !string.IsNullOrEmpty(downloadUrl))
result.Add((version, downloadUrl, releaseNotes));
}
+1 -2
View File
@@ -1863,8 +1863,7 @@ namespace Ink_Canvas
if (AvailableLatestVersion != null && Settings.Startup.IsAutoUpdate)
{
// 检查更新文件是否已下载
string updatesFolderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "AutoUpdate");
string statusFilePath = Path.Combine(updatesFolderPath, $"DownloadV{AvailableLatestVersion}Status.txt");
string statusFilePath = AutoUpdateHelper.GetUpdateDownloadStatusFilePath(AvailableLatestVersion);
if (File.Exists(statusFilePath) && File.ReadAllText(statusFilePath).Trim().ToLower() == "true")
{
+1 -2
View File
@@ -1147,8 +1147,7 @@ namespace Ink_Canvas
}
// 检查更新文件是否已下载
string updatesFolderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "AutoUpdate");
string statusFilePath = Path.Combine(updatesFolderPath, $"DownloadV{AvailableLatestVersion}Status.txt");
string statusFilePath = AutoUpdateHelper.GetUpdateDownloadStatusFilePath(AvailableLatestVersion);
if (!File.Exists(statusFilePath) || File.ReadAllText(statusFilePath).Trim().ToLower() != "true")
{
+11
View File
@@ -188,6 +188,15 @@ namespace Ink_Canvas
Beta
}
/// <summary>自动更新要下载的安装包架构(与当前运行进程的位数无关)。默认 32 位包;64 位包对应发布物 ZIP 文件名在 .zip 前增加 -x64。</summary>
public enum UpdatePackageArchitecture
{
/// <summary>32 位包,例如 InkCanvasForClass.CE.1.7.0.0.zip</summary>
X86 = 0,
/// <summary>64 位包,例如 InkCanvasForClass.CE.1.7.0.0-x64.zip</summary>
X64 = 1
}
/// <summary>
/// 遥测上传等级
/// </summary>
@@ -219,6 +228,8 @@ namespace Ink_Canvas
public string AutoUpdateWithSilenceEndTime { get; set; } = "22:00";
[JsonProperty("updateChannel")]
public UpdateChannel UpdateChannel { get; set; } = UpdateChannel.Release;
[JsonProperty("updatePackageArchitecture")]
public UpdatePackageArchitecture UpdatePackageArchitecture { get; set; } = UpdatePackageArchitecture.X86;
[JsonProperty("skippedVersion")]
public string SkippedVersion { get; set; } = "";
[JsonProperty("autoUpdatePauseUntilDate")]
@@ -1,4 +1,4 @@
using Ink_Canvas.Helpers;
using Ink_Canvas.Helpers;
using iNKORE.UI.WPF.Modern;
using iNKORE.UI.WPF.Modern.Controls;
using MdXaml;
@@ -500,8 +500,7 @@ namespace Ink_Canvas
if (string.IsNullOrEmpty(downloadUrl))
{
// 自动更新场景下,downloadUrl为null,直接用主下载目录
string updatesFolderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "AutoUpdate");
downloadUrl = Path.Combine(updatesFolderPath, $"InkCanvasForClass.CE.{version}.zip");
downloadUrl = AutoUpdateHelper.GetLocalUpdateZipFilePath(version);
}
LogHelper.WriteLogToFile($"AutoUpdate | 开始安装版本: {version}");
AutoUpdateHelper.InstallNewVersionApp(version, true);
@@ -157,6 +157,25 @@
</StackPanel>
</Border>
<Grid Height="54" Margin="0,0,0,16">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical" Margin="0,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Left" Grid.Column="0" MaxWidth="350">
<TextBlock Foreground="#2e3436" FontSize="14.5" Text="软件架构" HorizontalAlignment="Left"/>
<TextBlock Foreground="#9a9996" FontSize="11" Margin="0,3.5,0,0" Text="选择更新架构" HorizontalAlignment="Left" TextWrapping="Wrap"/>
</StackPanel>
<WrapPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,15,0" Grid.Column="1">
<Border x:Name="UpdateArchX86Border" Padding="13,7" CornerRadius="8" Background="#e1e1e1" Cursor="Hand" Tag="UpdateArch_X86" Margin="0,0,8,8" MouseLeftButtonDown="OptionButton_Click">
<TextBlock Foreground="#2e3436" FontSize="14" FontWeight="Bold" Text="32 位 (x86)"/>
</Border>
<Border x:Name="UpdateArchX64Border" Padding="13,7" CornerRadius="8" Cursor="Hand" Tag="UpdateArch_X64" Margin="0,0,8,8" MouseLeftButtonDown="OptionButton_Click">
<TextBlock Foreground="#2e3436" FontSize="14" Text="64 位 (x64)"/>
</Border>
</WrapPanel>
</Grid>
<Grid Height="54">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
@@ -48,7 +48,10 @@ namespace Ink_Canvas.Windows.SettingsViews
{
var version = Assembly.GetExecutingAssembly().GetName().Version;
var platform = Environment.Is64BitOperatingSystem ? "windows-x64" : "windows-x86";
CurrentVersionText.Text = $"当前版本: v{version} | {platform}";
var pkgArch = MainWindow.Settings.Startup.UpdatePackageArchitecture == UpdatePackageArchitecture.X64
? "更新包: 64位"
: "更新包: 32位";
CurrentVersionText.Text = $"当前版本: v{version} | {platform} | {pkgArch}";
LoadLastCheckTime();
@@ -111,6 +114,11 @@ namespace Ink_Canvas.Windows.SettingsViews
{
UpdateUpdateChannelButtons(UpdateChannel.Beta);
}
if (MainWindow.Settings.Startup.UpdatePackageArchitecture == UpdatePackageArchitecture.X64)
UpdateUpdateArchitectureButtons(UpdatePackageArchitecture.X64);
else
UpdateUpdateArchitectureButtons(UpdatePackageArchitecture.X86);
}
catch (Exception ex)
{
@@ -806,6 +814,79 @@ namespace Ink_Canvas.Windows.SettingsViews
LoadHistoryVersions();
LoadUpdateLogWithPriority(UpdateChannel.Beta);
break;
case "UpdateArch_X86":
MainWindowSettingsHelper.UpdateSettingDirectly(() =>
{
MainWindow.Settings.Startup.UpdatePackageArchitecture = UpdatePackageArchitecture.X86;
}, "UpdatePackageArchitecture");
UpdateUpdateArchitectureButtons(UpdatePackageArchitecture.X86);
MainWindow.SaveSettingsToFile();
RefreshVersionArchLabel();
break;
case "UpdateArch_X64":
MainWindowSettingsHelper.UpdateSettingDirectly(() =>
{
MainWindow.Settings.Startup.UpdatePackageArchitecture = UpdatePackageArchitecture.X64;
}, "UpdatePackageArchitecture");
UpdateUpdateArchitectureButtons(UpdatePackageArchitecture.X64);
MainWindow.SaveSettingsToFile();
RefreshVersionArchLabel();
break;
}
}
private void RefreshVersionArchLabel()
{
try
{
if (MainWindow.Settings == null || CurrentVersionText == null) return;
var version = Assembly.GetExecutingAssembly().GetName().Version;
var platform = Environment.Is64BitOperatingSystem ? "windows-x64" : "windows-x86";
var pkgArch = MainWindow.Settings.Startup.UpdatePackageArchitecture == UpdatePackageArchitecture.X64
? "更新包: 64位"
: "更新包: 32位";
CurrentVersionText.Text = $"当前版本: v{version} | {platform} | {pkgArch}";
}
catch { /* ignore */ }
}
private void UpdateUpdateArchitectureButtons(UpdatePackageArchitecture selected)
{
try
{
bool isDarkTheme = ThemeHelper.IsDarkTheme;
var selectedBrush = isDarkTheme ? new SolidColorBrush(Color.FromRgb(25, 25, 25)) : new SolidColorBrush(Color.FromRgb(225, 225, 225));
var unselectedBrush = new SolidColorBrush(Colors.Transparent);
if (UpdateArchX86Border != null)
{
bool isSel = selected == UpdatePackageArchitecture.X86;
UpdateArchX86Border.Background = isSel ? selectedBrush : unselectedBrush;
var tb = UpdateArchX86Border.Child as TextBlock;
if (tb != null)
{
tb.FontWeight = isSel ? FontWeights.Bold : FontWeights.Normal;
tb.Foreground = ThemeHelper.GetTextPrimaryBrush();
}
}
if (UpdateArchX64Border != null)
{
bool isSel = selected == UpdatePackageArchitecture.X64;
UpdateArchX64Border.Background = isSel ? selectedBrush : unselectedBrush;
var tb = UpdateArchX64Border.Child as TextBlock;
if (tb != null)
{
tb.FontWeight = isSel ? FontWeights.Bold : FontWeights.Normal;
tb.Foreground = ThemeHelper.GetTextPrimaryBrush();
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"更新软件架构按钮状态时出错: {ex.Message}");
}
}