diff --git a/Ink Canvas/App.xaml.cs b/Ink Canvas/App.xaml.cs index 6c378e01..18d81b14 100644 --- a/Ink Canvas/App.xaml.cs +++ b/Ink Canvas/App.xaml.cs @@ -16,6 +16,7 @@ using MessageBox = System.Windows.MessageBox; using Window = System.Windows.Window; using System.Collections.Generic; using System.Runtime.InteropServices; +using System.Net; namespace Ink_Canvas { @@ -48,6 +49,9 @@ namespace Ink_Canvas public App() { + // 配置TLS协议以支持Windows 7 + ConfigureTlsForWindows7(); + // 如果是看门狗子进程,直接进入看门狗主循环并终止主流程 var args = Environment.GetCommandLineArgs(); if (args.Length >= 2 && args[1] == "--watchdog") @@ -75,6 +79,41 @@ namespace Ink_Canvas this.Exit += App_Exit; // 注册退出事件 } + // 新增:配置TLS协议以支持Windows 7 + private void ConfigureTlsForWindows7() + { + try + { + // 检测操作系统版本 + var osVersion = Environment.OSVersion; + bool isWindows7 = osVersion.Version.Major == 6 && osVersion.Version.Minor == 1; + + if (isWindows7) + { + LogHelper.WriteLogToFile("检测到Windows 7系统,配置TLS协议支持", LogHelper.LogType.Info); + + // 启用所有TLS版本以支持Windows 7 + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; + + // 配置ServicePointManager以支持Windows 7 + ServicePointManager.DefaultConnectionLimit = 10; + ServicePointManager.Expect100Continue = false; + ServicePointManager.UseNagleAlgorithm = false; + + LogHelper.WriteLogToFile("TLS协议配置完成,已启用TLS 1.2/1.1/1.0支持", LogHelper.LogType.Info); + } + else + { + // 对于更新的Windows版本,不进行任何TLS配置,使用系统默认设置 + LogHelper.WriteLogToFile($"检测到Windows版本: {osVersion.VersionString},使用系统默认TLS配置", LogHelper.LogType.Info); + } + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"配置TLS协议时出错: {ex.Message}", LogHelper.LogType.Error); + } + } + // 新增:初始化崩溃监听器 private void InitializeCrashListeners() { diff --git a/Ink Canvas/AssemblyInfo.cs b/Ink Canvas/AssemblyInfo.cs index 83f0988b..0f179263 100644 --- a/Ink Canvas/AssemblyInfo.cs +++ b/Ink Canvas/AssemblyInfo.cs @@ -49,5 +49,5 @@ using System.Windows; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.7.1.0")] -[assembly: AssemblyFileVersion("1.7.1.0")] +[assembly: AssemblyVersion("1.7.1.3")] +[assembly: AssemblyFileVersion("1.7.1.3")] diff --git a/Ink Canvas/Helpers/AutoUpdateHelper.cs b/Ink Canvas/Helpers/AutoUpdateHelper.cs index 094e2445..53f0f5b5 100644 --- a/Ink Canvas/Helpers/AutoUpdateHelper.cs +++ b/Ink Canvas/Helpers/AutoUpdateHelper.cs @@ -11,6 +11,7 @@ using System.Windows.Controls; using System.IO.Compression; using System.Text; using System.Collections.Generic; +using Newtonsoft.Json; namespace Ink_Canvas.Helpers { @@ -18,583 +19,9 @@ namespace Ink_Canvas.Helpers { // 定义超时时间为10秒 private static readonly TimeSpan RequestTimeout = TimeSpan.FromSeconds(10); - - public static async Task CheckForUpdates(string proxy = null, UpdateChannel channel = UpdateChannel.Release) - { - try - { - string localVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString(); - LogHelper.WriteLogToFile($"AutoUpdate | Local version: {localVersion}"); - - string remoteAddress = proxy; - - // 根据通道选择URL - string primaryUrl, fallbackUrl; - - if (channel == UpdateChannel.Release) - { - // Release通道版本信息地址 - primaryUrl = "https://github.com/InkCanvasForClass/community/raw/refs/heads/main/AutomaticUpdateVersionControl.txt"; - fallbackUrl = "https://bgithub.xyz/InkCanvasForClass/community/raw/refs/heads/main/AutomaticUpdateVersionControl.txt"; - } - else - { - // Beta通道版本信息地址 - primaryUrl = "https://github.com/InkCanvasForClass/community-beta/raw/refs/heads/main/AutomaticUpdateVersionControl.txt"; - fallbackUrl = "https://bgithub.xyz/InkCanvasForClass/community-beta/raw/refs/heads/main/AutomaticUpdateVersionControl.txt"; - } - - LogHelper.WriteLogToFile($"AutoUpdate | Checking for updates on {channel} channel"); - - // 先尝试主地址 - remoteAddress += primaryUrl; - string remoteVersion = await GetRemoteVersion(remoteAddress); - - // 如果主地址失败,尝试备用地址 - if (remoteVersion == null) - { - LogHelper.WriteLogToFile($"AutoUpdate | Primary URL failed, trying fallback URL"); - remoteVersion = await GetRemoteVersion(proxy + fallbackUrl); - } - - if (remoteVersion != null) - { - LogHelper.WriteLogToFile($"AutoUpdate | Remote version: {remoteVersion}"); - Version local = new Version(localVersion); - Version remote = new Version(remoteVersion); - if (remote > local) - { - LogHelper.WriteLogToFile($"AutoUpdate | New version available: {remoteVersion}"); - return remoteVersion; - } - else - { - LogHelper.WriteLogToFile($"AutoUpdate | Current version is up to date"); - return null; - } - } - else - { - LogHelper.WriteLogToFile("AutoUpdate | Failed to retrieve remote version from both URLs.", LogHelper.LogType.Error); - return null; - } - } - catch (Exception ex) - { - LogHelper.WriteLogToFile($"AutoUpdate | Error in CheckForUpdates: {ex.Message}", LogHelper.LogType.Error); - return null; - } - } - - public static async Task GetRemoteVersion(string fileUrl) - { - using (HttpClient client = new HttpClient()) - { - try - { - // 设置超时时间为10秒 - client.Timeout = RequestTimeout; - - LogHelper.WriteLogToFile($"AutoUpdate | Sending HTTP request to: {fileUrl}"); - - // 使用带超时的Task.WhenAny来确保请求不会无限期等待 - var downloadTask = client.GetAsync(fileUrl); - var timeoutTask = Task.Delay(RequestTimeout); - - var completedTask = await Task.WhenAny(downloadTask, timeoutTask); - if (completedTask == timeoutTask) - { - LogHelper.WriteLogToFile($"AutoUpdate | Request timed out after {RequestTimeout.TotalSeconds} seconds", LogHelper.LogType.Error); - return null; - } - - // 请求完成,检查结果 - HttpResponseMessage response = await downloadTask; - - LogHelper.WriteLogToFile($"AutoUpdate | HTTP response status: {response.StatusCode}"); - response.EnsureSuccessStatusCode(); - - string content = await response.Content.ReadAsStringAsync(); - // Trim any whitespace, newlines, etc. - content = content.Trim(); - - // If the content contains HTML (likely the GitHub view page instead of raw content), - // try to extract the version number - if (content.Contains(" 0) - { - int endPos = content.IndexOf("", startPos); - if (endPos > startPos) - { - string tableContent = content.Substring(startPos, endPos - startPos); - // Look for the version number pattern (like 1.2.3 or 1.2.3.4) - var match = System.Text.RegularExpressions.Regex.Match(tableContent, @"(\d+\.\d+\.\d+(\.\d+)?)"); - if (match.Success) - { - content = match.Groups[1].Value; - LogHelper.WriteLogToFile($"AutoUpdate | Extracted version from HTML: {content}"); - } - else - { - LogHelper.WriteLogToFile($"AutoUpdate | Could not extract version from HTML content"); - return null; - } - } - } - } - - LogHelper.WriteLogToFile($"AutoUpdate | Response content: {content}"); - return content; - } - catch (HttpRequestException ex) - { - LogHelper.WriteLogToFile($"AutoUpdate | HTTP request error: {ex.Message}", LogHelper.LogType.Error); - } - catch (TaskCanceledException ex) - { - LogHelper.WriteLogToFile($"AutoUpdate | Request timed out: {ex.Message}", LogHelper.LogType.Error); - } - catch (Exception ex) - { - LogHelper.WriteLogToFile($"AutoUpdate | Error: {ex.Message}", LogHelper.LogType.Error); - } - - return null; - } - } - private static string updatesFolderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "AutoUpdate"); private static string statusFilePath = null; - public static async Task DownloadSetupFileAndSaveStatus(string version, string proxy = "", UpdateChannel channel = UpdateChannel.Release) - { - try - { - statusFilePath = Path.Combine(updatesFolderPath, $"DownloadV{version}Status.txt"); - - if (File.Exists(statusFilePath) && File.ReadAllText(statusFilePath).Trim().ToLower() == "true") - { - LogHelper.WriteLogToFile("AutoUpdate | Setup file already downloaded."); - return true; - } - - // Ensure update directory exists - if (!Directory.Exists(updatesFolderPath)) - { - Directory.CreateDirectory(updatesFolderPath); - LogHelper.WriteLogToFile($"AutoUpdate | Created updates directory: {updatesFolderPath}"); - } - - // 根据通道选择下载地址 - string primaryUrl, fallbackUrl; - - if (channel == UpdateChannel.Release) - { - // Release通道下载地址 - primaryUrl = $"{proxy}https://github.com/InkCanvasForClass/community/releases/download/{version}/InkCanvasForClass.CE.{version}.zip"; - fallbackUrl = $"{proxy}https://bgithub.xyz/InkCanvasForClass/community/releases/download/{version}/InkCanvasForClass.CE.{version}.zip"; - } - else - { - // Beta通道下载地址 - primaryUrl = $"{proxy}https://github.com/InkCanvasForClass/community-beta/releases/download/{version}/InkCanvasForClass.CE.{version}.zip"; - fallbackUrl = $"{proxy}https://bgithub.xyz/InkCanvasForClass/community-beta/releases/download/{version}/InkCanvasForClass.CE.{version}.zip"; - } - - LogHelper.WriteLogToFile($"AutoUpdate | Primary download URL: {primaryUrl}"); - - SaveDownloadStatus(false); - string zipFilePath = Path.Combine(updatesFolderPath, $"InkCanvasForClass.CE.{version}.zip"); - LogHelper.WriteLogToFile($"AutoUpdate | Target file path: {zipFilePath}"); - - // 先尝试主地址下载 - bool downloadSuccess = await DownloadFile(primaryUrl, zipFilePath); - - // 如果主地址下载失败,尝试备用地址 - if (!downloadSuccess) - { - LogHelper.WriteLogToFile($"AutoUpdate | Primary download failed, trying fallback URL: {fallbackUrl}"); - downloadSuccess = await DownloadFile(fallbackUrl, zipFilePath); - } - - if (downloadSuccess) - { - SaveDownloadStatus(true); - LogHelper.WriteLogToFile("AutoUpdate | Setup file successfully downloaded."); - return true; - } - else - { - LogHelper.WriteLogToFile("AutoUpdate | Failed to download the update file from both URLs.", LogHelper.LogType.Error); - return false; - } - } - catch (Exception ex) - { - LogHelper.WriteLogToFile($"AutoUpdate | Error downloading update: {ex.Message}", LogHelper.LogType.Error); - if (ex.InnerException != null) - { - LogHelper.WriteLogToFile($"AutoUpdate | Inner exception: {ex.InnerException.Message}", LogHelper.LogType.Error); - } - - SaveDownloadStatus(false); - return false; - } - } - - private static async Task DownloadFile(string fileUrl, string destinationPath) - { - using (HttpClient client = new HttpClient()) - { - try - { - // Configure client - client.Timeout = TimeSpan.FromMinutes(5); // 下载文件需要更长的超时时间 - client.DefaultRequestHeaders.Add("User-Agent", "ICC-CE Auto Updater"); - - LogHelper.WriteLogToFile($"AutoUpdate | Downloading from: {fileUrl}"); - - // 创建临时文件路径 - string tempFilePath = destinationPath + ".tmp"; - - // 确保目标目录存在 - string directory = Path.GetDirectoryName(destinationPath); - if (!Directory.Exists(directory)) - { - Directory.CreateDirectory(directory); - } - - // 使用带超时的Task.WhenAny来确保请求不会无限期等待 - var downloadTask = client.GetAsync(fileUrl, HttpCompletionOption.ResponseHeadersRead); - var initialTimeoutTask = Task.Delay(RequestTimeout); // 使用全局定义的10秒超时 - - var completedTask = await Task.WhenAny(downloadTask, initialTimeoutTask); - if (completedTask == initialTimeoutTask) - { - LogHelper.WriteLogToFile($"AutoUpdate | Initial connection timed out after 30 seconds", LogHelper.LogType.Error); - return false; - } - - // 请求完成,检查结果 - HttpResponseMessage response = await downloadTask; - LogHelper.WriteLogToFile($"AutoUpdate | HTTP response status: {response.StatusCode}"); - response.EnsureSuccessStatusCode(); - - // 获取文件总大小 - long? totalBytes = response.Content.Headers.ContentLength; - LogHelper.WriteLogToFile($"AutoUpdate | File size: {(totalBytes.HasValue ? (totalBytes.Value / 1024.0 / 1024.0).ToString("F2") + " MB" : "Unknown")}"); - - // 创建临时文件流 - using (var fileStream = new FileStream(tempFilePath, FileMode.Create, FileAccess.Write, FileShare.None)) - { - // 获取下载流 - using (var downloadStream = await response.Content.ReadAsStreamAsync()) - { - byte[] buffer = new byte[8192]; // 8KB buffer - long totalBytesRead = 0; - int bytesRead; - DateTime lastProgressUpdate = DateTime.Now; - - // 设置下载超时 - 如果60秒内没有数据传输,则认为下载超时 - var downloadTimeoutTask = Task.Delay(TimeSpan.FromSeconds(60)); - var readTask = Task.Run(async () => { - while ((bytesRead = await downloadStream.ReadAsync(buffer, 0, buffer.Length)) > 0) - { - await fileStream.WriteAsync(buffer, 0, bytesRead); - totalBytesRead += bytesRead; - - // 每5秒更新一次进度 - if ((DateTime.Now - lastProgressUpdate).TotalSeconds >= 5) - { - if (totalBytes.HasValue) - { - double percentage = (double)totalBytesRead / totalBytes.Value * 100; - LogHelper.WriteLogToFile($"AutoUpdate | Download progress: {percentage:F1}% ({(totalBytesRead / 1024.0 / 1024.0):F2} MB / {(totalBytes.Value / 1024.0 / 1024.0):F2} MB)"); - } - else - { - LogHelper.WriteLogToFile($"AutoUpdate | Downloaded: {(totalBytesRead / 1024.0 / 1024.0):F2} MB"); - } - lastProgressUpdate = DateTime.Now; - - // 重置下载超时 - downloadTimeoutTask = Task.Delay(TimeSpan.FromSeconds(60)); - } - } - return true; - }); - - // 等待下载完成或超时 - if (await Task.WhenAny(readTask, downloadTimeoutTask) == downloadTimeoutTask) - { - LogHelper.WriteLogToFile($"AutoUpdate | Download timed out after 60 seconds of inactivity", LogHelper.LogType.Error); - return false; - } - - // 确保下载任务完成 - bool downloadCompleted = await readTask; - - if (downloadCompleted) - { - LogHelper.WriteLogToFile($"AutoUpdate | Download completed: {(totalBytesRead / 1024.0 / 1024.0):F2} MB"); - } - } - } - - // 如果临时文件存在,则将其移动到目标位置 - if (File.Exists(tempFilePath)) - { - // 如果目标文件已存在,先删除 - if (File.Exists(destinationPath)) - { - File.Delete(destinationPath); - } - - File.Move(tempFilePath, destinationPath); - LogHelper.WriteLogToFile($"AutoUpdate | File saved to: {destinationPath}"); - return true; - } - - return false; - } - catch (HttpRequestException ex) - { - LogHelper.WriteLogToFile($"AutoUpdate | HTTP request error: {ex.Message}", LogHelper.LogType.Error); - } - catch (TaskCanceledException ex) - { - LogHelper.WriteLogToFile($"AutoUpdate | Download timed out: {ex.Message}", LogHelper.LogType.Error); - } - catch (Exception ex) - { - LogHelper.WriteLogToFile($"AutoUpdate | Error downloading file: {ex.Message}", LogHelper.LogType.Error); - if (ex.InnerException != null) - { - LogHelper.WriteLogToFile($"AutoUpdate | Inner exception: {ex.InnerException.Message}", LogHelper.LogType.Error); - } - } - - // 清理临时文件 - try - { - string tempFilePath = destinationPath + ".tmp"; - if (File.Exists(tempFilePath)) - { - File.Delete(tempFilePath); - } - } - catch { } - - return false; - } - } - - private static void SaveDownloadStatus(bool isSuccess) - { - try - { - if (statusFilePath == null) return; - - string directory = Path.GetDirectoryName(statusFilePath); - if (!Directory.Exists(directory)) - { - Directory.CreateDirectory(directory); - } - - File.WriteAllText(statusFilePath, isSuccess.ToString()); - } - catch (Exception ex) - { - LogHelper.WriteLogToFile($"AutoUpdate | Error saving download status: {ex.Message}", LogHelper.LogType.Error); - } - } - - public static void InstallNewVersionApp(string version, bool isInSilence) - { - try - { - string zipFilePath = Path.Combine(updatesFolderPath, $"InkCanvasForClass.CE.{version}.zip"); - LogHelper.WriteLogToFile($"AutoUpdate | Checking for ZIP file: {zipFilePath}"); - - if (!File.Exists(zipFilePath)) - { - LogHelper.WriteLogToFile($"AutoUpdate | ZIP file not found: {zipFilePath}", LogHelper.LogType.Error); - return; - } - - // Verify ZIP file size and validity - FileInfo fileInfo = new FileInfo(zipFilePath); - if (fileInfo.Length == 0) - { - LogHelper.WriteLogToFile($"AutoUpdate | ZIP file is empty, cannot continue", LogHelper.LogType.Error); - return; - } - LogHelper.WriteLogToFile($"AutoUpdate | ZIP file size: {fileInfo.Length} bytes"); - - // 获取当前应用程序路径和进程ID - string currentAppDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - int currentProcessId = Process.GetCurrentProcess().Id; - string appPath = Assembly.GetExecutingAssembly().Location; - - LogHelper.WriteLogToFile($"AutoUpdate | Current application directory: {currentAppDir}"); - LogHelper.WriteLogToFile($"AutoUpdate | Current process ID: {currentProcessId}"); - LogHelper.WriteLogToFile($"AutoUpdate | Silent update mode: {isInSilence}"); - - // 创建批处理文件来执行更新操作 - string batchFilePath = Path.Combine(Path.GetTempPath(), "UpdateICC_" + Guid.NewGuid().ToString().Substring(0, 8) + ".bat"); - LogHelper.WriteLogToFile($"AutoUpdate | Creating update batch file: {batchFilePath}"); - - // 构建批处理文件内容 - StringBuilder batchContent = new StringBuilder(); - batchContent.AppendLine("@echo off"); - - // 使窗口隐藏(使用VBS脚本运行隐藏窗口) - batchContent.AppendLine("echo Set objShell = CreateObject(\"WScript.Shell\") > \"%temp%\\hideme.vbs\""); - batchContent.AppendLine("echo objShell.Run \"cmd /c \"\"\" ^& WScript.Arguments(0) ^& \"\"\"\", 0, True >> \"%temp%\\hideme.vbs\""); - batchContent.AppendLine($"echo Wscript.Sleep 100 >> \"%temp%\\hideme.vbs\""); - - // 创建真正的更新批处理文件 - string updateBatPath = Path.Combine(Path.GetTempPath(), "ICCUpdate_" + Guid.NewGuid().ToString().Substring(0, 8) + ".bat"); - batchContent.AppendLine($"echo @echo off > \"{updateBatPath}\""); - - // 写入等待进程退出的代码到更新批处理文件 - batchContent.AppendLine($"echo set PROC_ID={currentProcessId} >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo :CHECK_PROCESS >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo tasklist /fi \"PID eq %PROC_ID%\" ^| find \"%PROC_ID%\" ^> nul >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo if %%ERRORLEVEL%% == 0 ( >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo timeout /t 1 /nobreak ^> nul >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo goto CHECK_PROCESS >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo ) >> \"{updateBatPath}\""); - - // 应用程序已关闭,开始更新操作 - batchContent.AppendLine($"echo echo Application closed, starting update process... >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo timeout /t 2 /nobreak ^> nul >> \"{updateBatPath}\""); - - // 创建临时解压目录 - string extractPath = Path.Combine(updatesFolderPath, $"Extract_{version}"); - batchContent.AppendLine($"echo echo Extracting update files... >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo if exist \"{extractPath}\" rd /s /q \"{extractPath}\" >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo mkdir \"{extractPath}\" >> \"{updateBatPath}\""); - - // PowerShell解压ZIP文件(因为批处理不直接支持ZIP解压) - batchContent.AppendLine($"echo powershell -command \"Expand-Archive -Path '{zipFilePath.Replace("'", "''")}' -DestinationPath '{extractPath.Replace("'", "''")}' -Force\" >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo if %%ERRORLEVEL%% neq 0 ( >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo goto ERROR_EXIT >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo ) >> \"{updateBatPath}\""); - - // 复制文件到应用程序目录 - batchContent.AppendLine($"echo echo Copying updated files to application directory... >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo xcopy /s /y /e \"{extractPath}\\*\" \"{currentAppDir}\\\" >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo if %%ERRORLEVEL%% neq 0 ( >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo goto ERROR_EXIT >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo ) >> \"{updateBatPath}\""); - - // 清理临时文件 - batchContent.AppendLine($"echo echo Cleaning up temporary files... >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo if exist \"{extractPath}\" rd /s /q \"{extractPath}\" >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo if exist \"{zipFilePath}\" del /f /q \"{zipFilePath}\" >> \"{updateBatPath}\""); - - // 启动更新后的应用程序 - batchContent.AppendLine($"echo echo Update completed successfully! >> \"{updateBatPath}\""); - - // 根据是否为静默更新模式决定是否自动启动应用程序 - if (isInSilence) - { - // 静默更新模式下,自动启动应用程序 - batchContent.AppendLine($"echo echo 自动启动应用程序... >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo start \"\" \"{appPath}\" >> \"{updateBatPath}\""); - } - else - { - // 非静默模式下,检查应用程序是否已经在运行 - batchContent.AppendLine($"echo :: 检查应用程序是否已经在运行 >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo tasklist /FI \"IMAGENAME eq Ink Canvas.exe\" | find /i \"Ink Canvas.exe\" > nul >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo if %%ERRORLEVEL%% neq 0 ( >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo echo 启动应用程序... >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo start \"\" \"{appPath}\" >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo ) else ( >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo echo 应用程序已经在运行,不再重复启动 >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo ) >> \"{updateBatPath}\""); - } - - batchContent.AppendLine($"echo exit /b 0 >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo goto EXIT >> \"{updateBatPath}\""); - - // 错误退出处理 - if (isInSilence) - { - // 静默模式下,不显示错误提示 - batchContent.AppendLine($"echo :ERROR_EXIT >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo echo Update failed! >> \"%temp%\\icc_update_error.log\" >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo exit /b 1 >> \"{updateBatPath}\""); - } - else - { - // 非静默模式下,显示错误提示 - batchContent.AppendLine($"echo :ERROR_EXIT >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo start \"\" cmd /c \"echo Update failed! ^& pause\" >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo exit /b 1 >> \"{updateBatPath}\""); - } - - // 删除批处理文件自身 - batchContent.AppendLine($"echo :EXIT >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo del \"{updateBatPath}\" >> \"{updateBatPath}\""); - batchContent.AppendLine($"echo exit >> \"{updateBatPath}\""); - - // 使用VBS脚本执行更新批处理文件(隐藏窗口) - batchContent.AppendLine($"wscript \"%temp%\\hideme.vbs\" \"{updateBatPath}\""); - batchContent.AppendLine("del \"%temp%\\hideme.vbs\""); - batchContent.AppendLine("exit"); - - // 写入批处理文件 - File.WriteAllText(batchFilePath, batchContent.ToString()); - LogHelper.WriteLogToFile($"AutoUpdate | Created update batch file"); - - // 启动批处理文件(隐藏窗口) - Process.Start(new ProcessStartInfo - { - FileName = batchFilePath, - CreateNoWindow = true, - UseShellExecute = true, - WindowStyle = ProcessWindowStyle.Hidden - }); - - LogHelper.WriteLogToFile($"AutoUpdate | Started update batch process with hidden window"); - - // 应用程序将由用户手动关闭或由MainWindow中的代码关闭 - } - catch (Exception ex) - { - LogHelper.WriteLogToFile($"AutoUpdate | Error preparing update installation: {ex.Message}", LogHelper.LogType.Error); - if (ex.InnerException != null) - { - LogHelper.WriteLogToFile($"AutoUpdate | Inner exception: {ex.InnerException.Message}", LogHelper.LogType.Error); - } - } - } - - private static async Task GetUrlDelay(string url) - { - try - { - using (var client = new System.Net.Http.HttpClient()) - { - client.Timeout = TimeSpan.FromSeconds(5); - var sw = System.Diagnostics.Stopwatch.StartNew(); - var resp = await client.SendAsync(new System.Net.Http.HttpRequestMessage(System.Net.Http.HttpMethod.Head, url)); - sw.Stop(); - if (resp.IsSuccessStatusCode) - return sw.ElapsedMilliseconds; - } - } - catch { } - return -1; - } - // 线路组结构体(包含版本、下载、日志地址) public class UpdateLineGroup { @@ -612,9 +39,9 @@ namespace Ink_Canvas.Helpers new UpdateLineGroup { GroupName = "GitHub主线", - VersionUrl = "https://github.com/InkCanvasForClass/community/raw/refs/heads/beta/AutomaticUpdateVersionControl.txt", + VersionUrl = "https://github.com/InkCanvasForClass/community/raw/refs/heads/main/AutomaticUpdateVersionControl.txt", DownloadUrlFormat = "https://github.com/InkCanvasForClass/community/releases/download/{0}/InkCanvasForClass.CE.{0}.zip", - LogUrl = "https://github.com/InkCanvasForClass/community/raw/refs/heads/beta/UpdateLog.md" + LogUrl = "https://github.com/InkCanvasForClass/community/raw/refs/heads/main/UpdateLog.md" }, new UpdateLineGroup { @@ -626,9 +53,9 @@ namespace Ink_Canvas.Helpers new UpdateLineGroup { GroupName = "kkgithub线路", - VersionUrl = "https://kkgithub.com/InkCanvasForClass/community/raw/refs/heads/beta/AutomaticUpdateVersionControl.txt", + VersionUrl = "https://kkgithub.com/InkCanvasForClass/community/raw/refs/heads/main/AutomaticUpdateVersionControl.txt", DownloadUrlFormat = "https://kkgithub.com/InkCanvasForClass/community/releases/download/{0}/InkCanvasForClass.CE.{0}.zip", - LogUrl = "https://kkgithub.com/InkCanvasForClass/community/raw/refs/heads/beta/UpdateLog.md" + LogUrl = "https://kkgithub.com/InkCanvasForClass/community/raw/refs/heads/main/UpdateLog.md" } } }, @@ -659,133 +86,950 @@ namespace Ink_Canvas.Helpers } }; - // 检测线路组延迟,只检测当前通道下的所有线路组,返回最快组 - private static async Task GetFastestLineGroup(UpdateChannel channel) - { - var groups = ChannelLineGroups[channel]; - long minDelay = long.MaxValue; - UpdateLineGroup bestGroup = null; - foreach (var group in groups) - { - var delay = await GetUrlDelay(group.VersionUrl); - if (delay >= 0 && delay < minDelay) - { - minDelay = delay; - bestGroup = group; - } - } - return bestGroup; - } - - // 新的自动选择线路组的更新检测方法,返回远程版本号和所用线路组 - public static async Task<(string remoteVersion, UpdateLineGroup lineGroup)> CheckForUpdatesWithAutoLine(UpdateChannel channel = UpdateChannel.Release, bool alwaysGetRemote = false) + // 检测URL延迟 + private static async Task GetUrlDelay(string url) { try { - string localVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString(); - LogHelper.WriteLogToFile($"AutoUpdate | Local version: {localVersion}"); - LogHelper.WriteLogToFile($"AutoUpdate | 检测通道 {channel} 下最快线路组..."); - var bestGroup = await GetFastestLineGroup(channel); - if (bestGroup == null) + // 检测是否为Windows 7 + var osVersion = Environment.OSVersion; + bool isWindows7 = osVersion.Version.Major == 6 && osVersion.Version.Minor == 1; + + if (isWindows7) { - LogHelper.WriteLogToFile("AutoUpdate | 所有线路组均不可用", LogHelper.LogType.Error); - return (null, null); - } - LogHelper.WriteLogToFile($"AutoUpdate | 选择最快线路组: {bestGroup.GroupName} {bestGroup.VersionUrl}"); - string remoteVersion = await GetRemoteVersion(bestGroup.VersionUrl); - if (remoteVersion != null) - { - LogHelper.WriteLogToFile($"AutoUpdate | Remote version: {remoteVersion}"); - Version local = new Version(localVersion); - Version remote = new Version(remoteVersion); - if (remote > local || alwaysGetRemote) + // Windows 7使用特殊配置 + using (var handler = new HttpClientHandler()) { - LogHelper.WriteLogToFile($"AutoUpdate | New version available or alwaysGetRemote: {remoteVersion}"); - return (remoteVersion, bestGroup); - } - else - { - LogHelper.WriteLogToFile($"AutoUpdate | Current version is up to date"); - return (null, bestGroup); + // 配置HttpClientHandler以支持Windows 7 + handler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true; + + using (var client = new HttpClient(handler)) + { + client.Timeout = TimeSpan.FromSeconds(5); + var sw = Stopwatch.StartNew(); + var resp = await client.SendAsync(new HttpRequestMessage(HttpMethod.Head, url)); + sw.Stop(); + if (resp.IsSuccessStatusCode) + return sw.ElapsedMilliseconds; + } } } else { - LogHelper.WriteLogToFile("AutoUpdate | 获取远程版本失败", LogHelper.LogType.Error); - return (null, bestGroup); + // 其他Windows版本使用标准配置 + using (var client = new HttpClient()) + { + client.Timeout = TimeSpan.FromSeconds(5); + var sw = Stopwatch.StartNew(); + var resp = await client.SendAsync(new HttpRequestMessage(HttpMethod.Head, url)); + sw.Stop(); + if (resp.IsSuccessStatusCode) + return sw.ElapsedMilliseconds; + } } } + catch { } + 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]; + var availableGroups = new List<(UpdateLineGroup group, long delay)>(); + + LogHelper.WriteLogToFile($"AutoUpdate | 开始检测通道 {channel} 下所有线路组延迟..."); + + foreach (var group in groups) + { + LogHelper.WriteLogToFile($"AutoUpdate | 检测线路组: {group.GroupName} ({group.VersionUrl})"); + var delay = await GetUrlDelay(group.VersionUrl); + if (delay >= 0) + { + LogHelper.WriteLogToFile($"AutoUpdate | 线路组 {group.GroupName} 延迟: {delay}ms"); + availableGroups.Add((group, delay)); + } + else + { + LogHelper.WriteLogToFile($"AutoUpdate | 线路组 {group.GroupName} 不可用", LogHelper.LogType.Warning); + } + } + + // 按延迟排序,延迟最小的排在前面 + var orderedGroups = availableGroups + .OrderBy(x => x.delay) + .Select(x => x.group) + .ToList(); + + if (orderedGroups.Count > 0) + { + 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 orderedGroups; + } + + // 获取远程版本号 + private static async Task GetRemoteVersion(string fileUrl) + { + // 检测是否为Windows 7 + var osVersion = Environment.OSVersion; + bool isWindows7 = osVersion.Version.Major == 6 && osVersion.Version.Minor == 1; + + if (isWindows7) + { + // Windows 7使用特殊配置 + using (var handler = new HttpClientHandler()) + { + try + { + // 配置HttpClientHandler以支持Windows 7 + handler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true; + + using (HttpClient client = new HttpClient(handler)) + { + client.Timeout = RequestTimeout; + LogHelper.WriteLogToFile($"AutoUpdate | 发送HTTP请求到: {fileUrl}"); + + var downloadTask = client.GetAsync(fileUrl); + var timeoutTask = Task.Delay(RequestTimeout); + + var completedTask = await Task.WhenAny(downloadTask, timeoutTask); + if (completedTask == timeoutTask) + { + LogHelper.WriteLogToFile($"AutoUpdate | 请求超时 ({RequestTimeout.TotalSeconds}秒)", LogHelper.LogType.Error); + return null; + } + + HttpResponseMessage response = await downloadTask; + LogHelper.WriteLogToFile($"AutoUpdate | HTTP响应状态: {response.StatusCode}"); + response.EnsureSuccessStatusCode(); + + string content = await response.Content.ReadAsStringAsync(); + content = content.Trim(); + + // 如果内容包含HTML(可能是GitHub页面而不是原始内容),尝试提取版本号 + if (content.Contains(" 0) + { + int endPos = content.IndexOf("", startPos); + if (endPos > startPos) + { + string tableContent = content.Substring(startPos, endPos - startPos); + var match = System.Text.RegularExpressions.Regex.Match(tableContent, @"(\d+\.\d+\.\d+(\.\d+)?)"); + if (match.Success) + { + content = match.Groups[1].Value; + LogHelper.WriteLogToFile($"AutoUpdate | 从HTML提取版本: {content}"); + } + else + { + LogHelper.WriteLogToFile($"AutoUpdate | 无法从HTML内容提取版本"); + return null; + } + } + } + } + + LogHelper.WriteLogToFile($"AutoUpdate | 响应内容: {content}"); + return content; + } + } + catch (HttpRequestException ex) + { + LogHelper.WriteLogToFile($"AutoUpdate | HTTP请求错误: {ex.Message}", LogHelper.LogType.Error); + } + catch (TaskCanceledException ex) + { + LogHelper.WriteLogToFile($"AutoUpdate | 请求超时: {ex.Message}", LogHelper.LogType.Error); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"AutoUpdate | 错误: {ex.Message}", LogHelper.LogType.Error); + } + + return null; + } + } + else + { + // 其他Windows版本使用标准配置 + using (HttpClient client = new HttpClient()) + { + try + { + client.Timeout = RequestTimeout; + LogHelper.WriteLogToFile($"AutoUpdate | 发送HTTP请求到: {fileUrl}"); + + var downloadTask = client.GetAsync(fileUrl); + var timeoutTask = Task.Delay(RequestTimeout); + + var completedTask = await Task.WhenAny(downloadTask, timeoutTask); + if (completedTask == timeoutTask) + { + LogHelper.WriteLogToFile($"AutoUpdate | 请求超时 ({RequestTimeout.TotalSeconds}秒)", LogHelper.LogType.Error); + return null; + } + + HttpResponseMessage response = await downloadTask; + LogHelper.WriteLogToFile($"AutoUpdate | HTTP响应状态: {response.StatusCode}"); + response.EnsureSuccessStatusCode(); + + string content = await response.Content.ReadAsStringAsync(); + content = content.Trim(); + + // 如果内容包含HTML(可能是GitHub页面而不是原始内容),尝试提取版本号 + if (content.Contains(" 0) + { + int endPos = content.IndexOf("", startPos); + if (endPos > startPos) + { + string tableContent = content.Substring(startPos, endPos - startPos); + var match = System.Text.RegularExpressions.Regex.Match(tableContent, @"(\d+\.\d+\.\d+(\.\d+)?)"); + if (match.Success) + { + content = match.Groups[1].Value; + LogHelper.WriteLogToFile($"AutoUpdate | 从HTML提取版本: {content}"); + } + else + { + LogHelper.WriteLogToFile($"AutoUpdate | 无法从HTML内容提取版本"); + return null; + } + } + } + } + + LogHelper.WriteLogToFile($"AutoUpdate | 响应内容: {content}"); + return content; + } + catch (HttpRequestException ex) + { + LogHelper.WriteLogToFile($"AutoUpdate | HTTP请求错误: {ex.Message}", LogHelper.LogType.Error); + } + catch (TaskCanceledException ex) + { + LogHelper.WriteLogToFile($"AutoUpdate | 请求超时: {ex.Message}", LogHelper.LogType.Error); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"AutoUpdate | 错误: {ex.Message}", LogHelper.LogType.Error); + } + + return null; + } + } + } + + // 主要的更新检测方法(优先检测延迟,失败时自动切换线路组) + public static async Task<(string remoteVersion, UpdateLineGroup lineGroup)> CheckForUpdates(UpdateChannel channel = UpdateChannel.Release, bool alwaysGetRemote = false) + { + try + { + string localVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString(); + LogHelper.WriteLogToFile($"AutoUpdate | 本地版本: {localVersion}"); + LogHelper.WriteLogToFile($"AutoUpdate | 检测通道 {channel} 下最快线路组..."); + + // 获取所有可用线路组(按延迟排序) + var availableGroups = await GetAvailableLineGroupsOrdered(channel); + if (availableGroups.Count == 0) + { + LogHelper.WriteLogToFile("AutoUpdate | 所有线路组均不可用", LogHelper.LogType.Error); + return (null, null); + } + + // 依次尝试每个线路组,直到成功获取版本信息 + foreach (var group in availableGroups) + { + LogHelper.WriteLogToFile($"AutoUpdate | 尝试使用线路组获取版本信息: {group.GroupName}"); + string remoteVersion = await GetRemoteVersion(group.VersionUrl); + + if (remoteVersion != null) + { + 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 | 线路组 {group.GroupName} 获取版本失败,尝试下一个线路组", LogHelper.LogType.Warning); + } + } + + LogHelper.WriteLogToFile("AutoUpdate | 所有线路组均无法获取版本信息", LogHelper.LogType.Error); + return (null, null); + } catch (Exception ex) { - LogHelper.WriteLogToFile($"AutoUpdate | Error in CheckForUpdatesWithAutoLine: {ex.Message}", LogHelper.LogType.Error); + LogHelper.WriteLogToFile($"AutoUpdate | CheckForUpdates错误: {ex.Message}", LogHelper.LogType.Error); return (null, null); } } // 使用指定线路组下载新版 - public static async Task DownloadSetupFileWithLineGroup(string version, UpdateLineGroup group) + 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 { - string url = string.Format(group.DownloadUrlFormat, version); + statusFilePath = Path.Combine(updatesFolderPath, $"DownloadV{version}Status.txt"); + + if (File.Exists(statusFilePath) && File.ReadAllText(statusFilePath).Trim().ToLower() == "true") + { + LogHelper.WriteLogToFile("AutoUpdate | 安装包已下载"); + return true; + } + + // 确保更新目录存在 + if (!Directory.Exists(updatesFolderPath)) + { + Directory.CreateDirectory(updatesFolderPath); + LogHelper.WriteLogToFile($"AutoUpdate | 创建更新目录: {updatesFolderPath}"); + } + string zipFilePath = Path.Combine(updatesFolderPath, $"InkCanvasForClass.CE.{version}.zip"); - LogHelper.WriteLogToFile($"AutoUpdate | Downloading from: {url}"); - return await DownloadFile(url, zipFilePath); + LogHelper.WriteLogToFile($"AutoUpdate | 目标文件路径: {zipFilePath}"); + + SaveDownloadStatus(false); + + // 依次尝试每个线路组 + 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); + } + } + + LogHelper.WriteLogToFile("AutoUpdate | 所有线路组下载均失败", LogHelper.LogType.Error); + return false; } catch (Exception ex) { - LogHelper.WriteLogToFile($"AutoUpdate | Error in DownloadSetupFileWithLineGroup: {ex.Message}", LogHelper.LogType.Error); + LogHelper.WriteLogToFile($"AutoUpdate | 下载更新时出错: {ex.Message}", LogHelper.LogType.Error); + if (ex.InnerException != null) + { + LogHelper.WriteLogToFile($"AutoUpdate | 内部异常: {ex.InnerException.Message}", LogHelper.LogType.Error); + } + + SaveDownloadStatus(false); return false; } } + // 下载文件的具体实现 + private static async Task DownloadFile(string fileUrl, string destinationPath) + { + // 检测是否为Windows 7 + var osVersion = Environment.OSVersion; + bool isWindows7 = osVersion.Version.Major == 6 && osVersion.Version.Minor == 1; + + if (isWindows7) + { + // Windows 7使用特殊配置 + using (var handler = new HttpClientHandler()) + { + try + { + // 配置HttpClientHandler以支持Windows 7 + handler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true; + + using (HttpClient client = new HttpClient(handler)) + { + client.Timeout = TimeSpan.FromMinutes(5); + client.DefaultRequestHeaders.Add("User-Agent", "ICC-CE Auto Updater"); + + LogHelper.WriteLogToFile($"AutoUpdate | 开始下载: {fileUrl}"); + + string tempFilePath = destinationPath + ".tmp"; + + string directory = Path.GetDirectoryName(destinationPath); + if (!Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + + var downloadTask = client.GetAsync(fileUrl, HttpCompletionOption.ResponseHeadersRead); + var initialTimeoutTask = Task.Delay(RequestTimeout); + + var completedTask = await Task.WhenAny(downloadTask, initialTimeoutTask); + if (completedTask == initialTimeoutTask) + { + LogHelper.WriteLogToFile($"AutoUpdate | 初始连接超时", LogHelper.LogType.Error); + return false; + } + + HttpResponseMessage response = await downloadTask; + LogHelper.WriteLogToFile($"AutoUpdate | HTTP响应状态: {response.StatusCode}"); + response.EnsureSuccessStatusCode(); + + long? totalBytes = response.Content.Headers.ContentLength; + LogHelper.WriteLogToFile($"AutoUpdate | 文件大小: {(totalBytes.HasValue ? (totalBytes.Value / 1024.0 / 1024.0).ToString("F2") + " MB" : "未知")}"); + + using (var fileStream = new FileStream(tempFilePath, FileMode.Create, FileAccess.Write, FileShare.None)) + { + using (var downloadStream = await response.Content.ReadAsStreamAsync()) + { + byte[] buffer = new byte[8192]; + long totalBytesRead = 0; + int bytesRead; + DateTime lastProgressUpdate = DateTime.Now; + + var downloadTimeoutTask = Task.Delay(TimeSpan.FromSeconds(60)); + var readTask = Task.Run(async () => { + while ((bytesRead = await downloadStream.ReadAsync(buffer, 0, buffer.Length)) > 0) + { + await fileStream.WriteAsync(buffer, 0, bytesRead); + totalBytesRead += bytesRead; + + if ((DateTime.Now - lastProgressUpdate).TotalSeconds >= 5) + { + if (totalBytes.HasValue) + { + double percentage = (double)totalBytesRead / totalBytes.Value * 100; + LogHelper.WriteLogToFile($"AutoUpdate | 下载进度: {percentage:F1}% ({(totalBytesRead / 1024.0 / 1024.0):F2} MB / {(totalBytes.Value / 1024.0 / 1024.0):F2} MB)"); + } + else + { + LogHelper.WriteLogToFile($"AutoUpdate | 已下载: {(totalBytesRead / 1024.0 / 1024.0):F2} MB"); + } + lastProgressUpdate = DateTime.Now; + downloadTimeoutTask = Task.Delay(TimeSpan.FromSeconds(60)); + } + } + return true; + }); + + if (await Task.WhenAny(readTask, downloadTimeoutTask) == downloadTimeoutTask) + { + LogHelper.WriteLogToFile($"AutoUpdate | 下载超时(60秒无数据传输)", LogHelper.LogType.Error); + return false; + } + + bool downloadCompleted = await readTask; + + if (downloadCompleted) + { + LogHelper.WriteLogToFile($"AutoUpdate | 下载完成: {(totalBytesRead / 1024.0 / 1024.0):F2} MB"); + } + } + } + + if (File.Exists(tempFilePath)) + { + if (File.Exists(destinationPath)) + { + File.Delete(destinationPath); + } + + File.Move(tempFilePath, destinationPath); + LogHelper.WriteLogToFile($"AutoUpdate | 文件保存到: {destinationPath}"); + return true; + } + + return false; + } + } + catch (HttpRequestException ex) + { + LogHelper.WriteLogToFile($"AutoUpdate | HTTP请求错误: {ex.Message}", LogHelper.LogType.Error); + } + catch (TaskCanceledException ex) + { + LogHelper.WriteLogToFile($"AutoUpdate | 下载超时: {ex.Message}", LogHelper.LogType.Error); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"AutoUpdate | 下载文件时出错: {ex.Message}", LogHelper.LogType.Error); + if (ex.InnerException != null) + { + LogHelper.WriteLogToFile($"AutoUpdate | 内部异常: {ex.InnerException.Message}", LogHelper.LogType.Error); + } + } + + try + { + string tempFilePath = destinationPath + ".tmp"; + if (File.Exists(tempFilePath)) + { + File.Delete(tempFilePath); + } + } + catch { } + + return false; + } + } + else + { + // 其他Windows版本使用标准配置 + using (HttpClient client = new HttpClient()) + { + try + { + client.Timeout = TimeSpan.FromMinutes(5); + client.DefaultRequestHeaders.Add("User-Agent", "ICC-CE Auto Updater"); + + LogHelper.WriteLogToFile($"AutoUpdate | 开始下载: {fileUrl}"); + + string tempFilePath = destinationPath + ".tmp"; + + string directory = Path.GetDirectoryName(destinationPath); + if (!Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + + var downloadTask = client.GetAsync(fileUrl, HttpCompletionOption.ResponseHeadersRead); + var initialTimeoutTask = Task.Delay(RequestTimeout); + + var completedTask = await Task.WhenAny(downloadTask, initialTimeoutTask); + if (completedTask == initialTimeoutTask) + { + LogHelper.WriteLogToFile($"AutoUpdate | 初始连接超时", LogHelper.LogType.Error); + return false; + } + + HttpResponseMessage response = await downloadTask; + LogHelper.WriteLogToFile($"AutoUpdate | HTTP响应状态: {response.StatusCode}"); + response.EnsureSuccessStatusCode(); + + long? totalBytes = response.Content.Headers.ContentLength; + LogHelper.WriteLogToFile($"AutoUpdate | 文件大小: {(totalBytes.HasValue ? (totalBytes.Value / 1024.0 / 1024.0).ToString("F2") + " MB" : "未知")}"); + + using (var fileStream = new FileStream(tempFilePath, FileMode.Create, FileAccess.Write, FileShare.None)) + { + using (var downloadStream = await response.Content.ReadAsStreamAsync()) + { + byte[] buffer = new byte[8192]; + long totalBytesRead = 0; + int bytesRead; + DateTime lastProgressUpdate = DateTime.Now; + + var downloadTimeoutTask = Task.Delay(TimeSpan.FromSeconds(60)); + var readTask = Task.Run(async () => { + while ((bytesRead = await downloadStream.ReadAsync(buffer, 0, buffer.Length)) > 0) + { + await fileStream.WriteAsync(buffer, 0, bytesRead); + totalBytesRead += bytesRead; + + if ((DateTime.Now - lastProgressUpdate).TotalSeconds >= 5) + { + if (totalBytes.HasValue) + { + double percentage = (double)totalBytesRead / totalBytes.Value * 100; + LogHelper.WriteLogToFile($"AutoUpdate | 下载进度: {percentage:F1}% ({(totalBytesRead / 1024.0 / 1024.0):F2} MB / {(totalBytes.Value / 1024.0 / 1024.0):F2} MB)"); + } + else + { + LogHelper.WriteLogToFile($"AutoUpdate | 已下载: {(totalBytesRead / 1024.0 / 1024.0):F2} MB"); + } + lastProgressUpdate = DateTime.Now; + downloadTimeoutTask = Task.Delay(TimeSpan.FromSeconds(60)); + } + } + return true; + }); + + if (await Task.WhenAny(readTask, downloadTimeoutTask) == downloadTimeoutTask) + { + LogHelper.WriteLogToFile($"AutoUpdate | 下载超时(60秒无数据传输)", LogHelper.LogType.Error); + return false; + } + + bool downloadCompleted = await readTask; + + if (downloadCompleted) + { + LogHelper.WriteLogToFile($"AutoUpdate | 下载完成: {(totalBytesRead / 1024.0 / 1024.0):F2} MB"); + } + } + } + + if (File.Exists(tempFilePath)) + { + if (File.Exists(destinationPath)) + { + File.Delete(destinationPath); + } + + File.Move(tempFilePath, destinationPath); + LogHelper.WriteLogToFile($"AutoUpdate | 文件保存到: {destinationPath}"); + return true; + } + + return false; + } + catch (HttpRequestException ex) + { + LogHelper.WriteLogToFile($"AutoUpdate | HTTP请求错误: {ex.Message}", LogHelper.LogType.Error); + } + catch (TaskCanceledException ex) + { + LogHelper.WriteLogToFile($"AutoUpdate | 下载超时: {ex.Message}", LogHelper.LogType.Error); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"AutoUpdate | 下载文件时出错: {ex.Message}", LogHelper.LogType.Error); + if (ex.InnerException != null) + { + LogHelper.WriteLogToFile($"AutoUpdate | 内部异常: {ex.InnerException.Message}", LogHelper.LogType.Error); + } + } + + try + { + string tempFilePath = destinationPath + ".tmp"; + if (File.Exists(tempFilePath)) + { + File.Delete(tempFilePath); + } + } + catch { } + + return false; + } + } + } + + // 保存下载状态 + private static void SaveDownloadStatus(bool isSuccess) + { + try + { + if (statusFilePath == null) return; + + string directory = Path.GetDirectoryName(statusFilePath); + if (!Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + + File.WriteAllText(statusFilePath, isSuccess.ToString()); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"AutoUpdate | 保存下载状态时出错: {ex.Message}", LogHelper.LogType.Error); + } + } + + // 安装新版本应用 + public static void InstallNewVersionApp(string version, bool isInSilence) + { + try + { + // 在更新前备份设置文件 + try + { + if (MainWindow.Settings.Advanced.IsAutoBackupBeforeUpdate) + { + string backupDir = Path.Combine(App.RootPath, "Backups"); + if (!Directory.Exists(backupDir)) + { + Directory.CreateDirectory(backupDir); + LogHelper.WriteLogToFile($"创建备份目录: {backupDir}", LogHelper.LogType.Info); + } + + string backupFileName = $"Settings_BeforeUpdate_v{version}_{DateTime.Now:yyyyMMdd_HHmmss}.json"; + string backupPath = Path.Combine(backupDir, backupFileName); + + string settingsJson = JsonConvert.SerializeObject(MainWindow.Settings, Formatting.Indented); + File.WriteAllText(backupPath, settingsJson); + + LogHelper.WriteLogToFile($"更新前自动备份设置成功: {backupPath}", LogHelper.LogType.Info); + } + else + { + LogHelper.WriteLogToFile("更新前自动备份功能已禁用,跳过备份", LogHelper.LogType.Info); + } + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"更新前自动备份设置时出错: {ex.Message}", LogHelper.LogType.Error); + } + + string zipFilePath = Path.Combine(updatesFolderPath, $"InkCanvasForClass.CE.{version}.zip"); + LogHelper.WriteLogToFile($"AutoUpdate | 检查ZIP文件: {zipFilePath}"); + + if (!File.Exists(zipFilePath)) + { + LogHelper.WriteLogToFile($"AutoUpdate | ZIP文件未找到: {zipFilePath}", LogHelper.LogType.Error); + return; + } + + FileInfo fileInfo = new FileInfo(zipFilePath); + if (fileInfo.Length == 0) + { + LogHelper.WriteLogToFile($"AutoUpdate | ZIP文件为空,无法继续", LogHelper.LogType.Error); + return; + } + LogHelper.WriteLogToFile($"AutoUpdate | ZIP文件大小: {fileInfo.Length} 字节"); + + string currentAppDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + int currentProcessId = Process.GetCurrentProcess().Id; + string appPath = Assembly.GetExecutingAssembly().Location; + + LogHelper.WriteLogToFile($"AutoUpdate | 当前应用程序目录: {currentAppDir}"); + LogHelper.WriteLogToFile($"AutoUpdate | 当前进程ID: {currentProcessId}"); + LogHelper.WriteLogToFile($"AutoUpdate | 静默更新模式: {isInSilence}"); + + string batchFilePath = Path.Combine(Path.GetTempPath(), "UpdateICC_" + Guid.NewGuid().ToString().Substring(0, 8) + ".bat"); + LogHelper.WriteLogToFile($"AutoUpdate | 创建更新批处理文件: {batchFilePath}"); + + StringBuilder batchContent = new StringBuilder(); + batchContent.AppendLine("@echo off"); + + batchContent.AppendLine("echo Set objShell = CreateObject(\"WScript.Shell\") > \"%temp%\\hideme.vbs\""); + batchContent.AppendLine("echo objShell.Run \"cmd /c \"\"\" ^& WScript.Arguments(0) ^& \"\"\"\", 0, True >> \"%temp%\\hideme.vbs\""); + batchContent.AppendLine($"echo Wscript.Sleep 100 >> \"%temp%\\hideme.vbs\""); + + string updateBatPath = Path.Combine(Path.GetTempPath(), "ICCUpdate_" + Guid.NewGuid().ToString().Substring(0, 8) + ".bat"); + batchContent.AppendLine($"echo @echo off > \"{updateBatPath}\""); + + batchContent.AppendLine($"echo set PROC_ID={currentProcessId} >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo :CHECK_PROCESS >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo tasklist /fi \"PID eq %PROC_ID%\" ^| find \"%PROC_ID%\" ^> nul >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo if %%ERRORLEVEL%% == 0 ( >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo timeout /t 1 /nobreak ^> nul >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo goto CHECK_PROCESS >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo ) >> \"{updateBatPath}\""); + + batchContent.AppendLine($"echo echo Application closed, starting update process... >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo timeout /t 2 /nobreak ^> nul >> \"{updateBatPath}\""); + + string extractPath = Path.Combine(updatesFolderPath, $"Extract_{version}"); + batchContent.AppendLine($"echo echo Extracting update files... >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo if exist \"{extractPath}\" rd /s /q \"{extractPath}\" >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo mkdir \"{extractPath}\" >> \"{updateBatPath}\""); + + batchContent.AppendLine($"echo powershell -command \"Expand-Archive -Path '{zipFilePath.Replace("'", "''")}' -DestinationPath '{extractPath.Replace("'", "''")}' -Force\" >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo if %%ERRORLEVEL%% neq 0 ( >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo goto ERROR_EXIT >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo ) >> \"{updateBatPath}\""); + + batchContent.AppendLine($"echo echo Copying updated files to application directory... >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo xcopy /s /y /e \"{extractPath}\\*\" \"{currentAppDir}\\\" >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo if %%ERRORLEVEL%% neq 0 ( >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo goto ERROR_EXIT >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo ) >> \"{updateBatPath}\""); + + batchContent.AppendLine($"echo echo Cleaning up temporary files... >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo if exist \"{extractPath}\" rd /s /q \"{extractPath}\" >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo if exist \"{zipFilePath}\" del /f /q \"{zipFilePath}\" >> \"{updateBatPath}\""); + + batchContent.AppendLine($"echo echo Update completed successfully! >> \"{updateBatPath}\""); + + if (isInSilence) + { + batchContent.AppendLine($"echo echo 自动启动应用程序... >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo start \"\" \"{appPath}\" >> \"{updateBatPath}\""); + } + else + { + batchContent.AppendLine($"echo :: 检查应用程序是否已经在运行 >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo tasklist /FI \"IMAGENAME eq Ink Canvas.exe\" | find /i \"Ink Canvas.exe\" > nul >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo if %%ERRORLEVEL%% neq 0 ( >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo echo 启动应用程序... >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo start \"\" \"{appPath}\" >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo ) else ( >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo echo 应用程序已经在运行,不再重复启动 >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo ) >> \"{updateBatPath}\""); + } + + batchContent.AppendLine($"echo exit /b 0 >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo goto EXIT >> \"{updateBatPath}\""); + + if (isInSilence) + { + batchContent.AppendLine($"echo :ERROR_EXIT >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo echo Update failed! >> \"%temp%\\icc_update_error.log\" >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo exit /b 1 >> \"{updateBatPath}\""); + } + else + { + batchContent.AppendLine($"echo :ERROR_EXIT >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo start \"\" cmd /c \"echo Update failed! ^& pause\" >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo exit /b 1 >> \"{updateBatPath}\""); + } + + batchContent.AppendLine($"echo :EXIT >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo del \"{updateBatPath}\" >> \"{updateBatPath}\""); + batchContent.AppendLine($"echo exit >> \"{updateBatPath}\""); + + batchContent.AppendLine($"wscript \"%temp%\\hideme.vbs\" \"{updateBatPath}\""); + batchContent.AppendLine("del \"%temp%\\hideme.vbs\""); + batchContent.AppendLine("exit"); + + File.WriteAllText(batchFilePath, batchContent.ToString()); + LogHelper.WriteLogToFile($"AutoUpdate | 创建更新批处理文件完成"); + + Process.Start(new ProcessStartInfo + { + FileName = batchFilePath, + CreateNoWindow = true, + UseShellExecute = true, + WindowStyle = ProcessWindowStyle.Hidden + }); + + LogHelper.WriteLogToFile($"AutoUpdate | 启动更新批处理进程(隐藏窗口)"); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"AutoUpdate | 准备更新安装时出错: {ex.Message}", LogHelper.LogType.Error); + if (ex.InnerException != null) + { + LogHelper.WriteLogToFile($"AutoUpdate | 内部异常: {ex.InnerException.Message}", LogHelper.LogType.Error); + } + } + } + + // 获取远程内容的通用方法 + public static async Task GetRemoteContent(string fileUrl) + { + // 检测是否为Windows 7 + var osVersion = Environment.OSVersion; + bool isWindows7 = osVersion.Version.Major == 6 && osVersion.Version.Minor == 1; + + if (isWindows7) + { + // Windows 7使用特殊配置 + using (var handler = new HttpClientHandler()) + { + try + { + // 配置HttpClientHandler以支持Windows 7 + handler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true; + + using (HttpClient client = new HttpClient(handler)) + { + client.Timeout = RequestTimeout; + LogHelper.WriteLogToFile($"AutoUpdate | 发送HTTP请求到: {fileUrl}"); + var downloadTask = client.GetAsync(fileUrl); + var timeoutTask = Task.Delay(RequestTimeout); + var completedTask = await Task.WhenAny(downloadTask, timeoutTask); + if (completedTask == timeoutTask) + { + LogHelper.WriteLogToFile($"AutoUpdate | 请求超时 ({RequestTimeout.TotalSeconds}秒)", LogHelper.LogType.Error); + return null; + } + HttpResponseMessage response = await downloadTask; + LogHelper.WriteLogToFile($"AutoUpdate | HTTP响应状态: {response.StatusCode}"); + response.EnsureSuccessStatusCode(); + string content = await response.Content.ReadAsStringAsync(); + return content; + } + } + catch (HttpRequestException ex) + { + LogHelper.WriteLogToFile($"AutoUpdate | HTTP请求错误: {ex.Message}", LogHelper.LogType.Error); + } + catch (TaskCanceledException ex) + { + LogHelper.WriteLogToFile($"AutoUpdate | 请求超时: {ex.Message}", LogHelper.LogType.Error); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"AutoUpdate | 错误: {ex.Message}", LogHelper.LogType.Error); + } + return null; + } + } + else + { + // 其他Windows版本使用标准配置 + using (HttpClient client = new HttpClient()) + { + try + { + client.Timeout = RequestTimeout; + LogHelper.WriteLogToFile($"AutoUpdate | 发送HTTP请求到: {fileUrl}"); + var downloadTask = client.GetAsync(fileUrl); + var timeoutTask = Task.Delay(RequestTimeout); + var completedTask = await Task.WhenAny(downloadTask, timeoutTask); + if (completedTask == timeoutTask) + { + LogHelper.WriteLogToFile($"AutoUpdate | 请求超时 ({RequestTimeout.TotalSeconds}秒)", LogHelper.LogType.Error); + return null; + } + HttpResponseMessage response = await downloadTask; + LogHelper.WriteLogToFile($"AutoUpdate | HTTP响应状态: {response.StatusCode}"); + response.EnsureSuccessStatusCode(); + string content = await response.Content.ReadAsStringAsync(); + return content; + } + catch (HttpRequestException ex) + { + LogHelper.WriteLogToFile($"AutoUpdate | HTTP请求错误: {ex.Message}", LogHelper.LogType.Error); + } + catch (TaskCanceledException ex) + { + LogHelper.WriteLogToFile($"AutoUpdate | 请求超时: {ex.Message}", LogHelper.LogType.Error); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"AutoUpdate | 错误: {ex.Message}", LogHelper.LogType.Error); + } + return null; + } + } + } + // 使用指定线路组获取更新日志 public static async Task GetUpdateLogWithLineGroup(UpdateLineGroup group) { - return await AutoUpdateHelper.GetRemoteContent(group.LogUrl); + return await GetRemoteContent(group.LogUrl); } - // 获取远程内容的通用方法(public 以便线路组方法调用) - public static async Task GetRemoteContent(string fileUrl) - { - using (HttpClient client = new HttpClient()) - { - try - { - // 设置超时时间为10秒 - client.Timeout = RequestTimeout; - LogHelper.WriteLogToFile($"AutoUpdate | Sending HTTP request to: {fileUrl}"); - var downloadTask = client.GetAsync(fileUrl); - var timeoutTask = Task.Delay(RequestTimeout); - var completedTask = await Task.WhenAny(downloadTask, timeoutTask); - if (completedTask == timeoutTask) - { - LogHelper.WriteLogToFile($"AutoUpdate | Request timed out after {RequestTimeout.TotalSeconds} seconds", LogHelper.LogType.Error); - return null; - } - HttpResponseMessage response = await downloadTask; - LogHelper.WriteLogToFile($"AutoUpdate | HTTP response status: {response.StatusCode}"); - response.EnsureSuccessStatusCode(); - string content = await response.Content.ReadAsStringAsync(); - return content; - } - catch (HttpRequestException ex) - { - LogHelper.WriteLogToFile($"AutoUpdate | HTTP request error: {ex.Message}", LogHelper.LogType.Error); - } - catch (TaskCanceledException ex) - { - LogHelper.WriteLogToFile($"AutoUpdate | Request timed out: {ex.Message}", LogHelper.LogType.Error); - } - catch (Exception ex) - { - LogHelper.WriteLogToFile($"AutoUpdate | Error: {ex.Message}", LogHelper.LogType.Error); - } - return null; - } - } - - // 兼容旧接口:获取更新日志(自动选择最快线路组) + // 获取更新日志(自动选择最快线路组) public static async Task GetUpdateLog(UpdateChannel channel = UpdateChannel.Release) { var group = await GetFastestLineGroup(channel); @@ -793,14 +1037,13 @@ namespace Ink_Canvas.Helpers return await GetUpdateLogWithLineGroup(group); } - // 兼容旧接口:删除更新文件夹 + // 删除更新文件夹 public static void DeleteUpdatesFolder() { try { if (Directory.Exists(updatesFolderPath)) { - // Try to delete all files first in case of locking issues foreach (string file in Directory.GetFiles(updatesFolderPath, "*", SearchOption.AllDirectories)) { try { File.Delete(file); } catch { } @@ -815,27 +1058,31 @@ namespace Ink_Canvas.Helpers catch { } } - // 兼容旧接口:版本修复方法,强制下载并安装指定通道的最新版本 + // 版本修复方法,强制下载并安装指定通道的最新版本 public static async Task FixVersion(UpdateChannel channel = UpdateChannel.Release) { try { - LogHelper.WriteLogToFile($"AutoUpdate | Starting version fix for {channel} channel"); + LogHelper.WriteLogToFile($"AutoUpdate | 开始修复版本,通道: {channel}"); + // 获取远程版本号(自动选择最快线路组,始终下载远程版本) - var (remoteVersion, group) = await CheckForUpdatesWithAutoLine(channel, true); + var (remoteVersion, group) = await CheckForUpdates(channel, true); if (string.IsNullOrEmpty(remoteVersion) || group == null) { - LogHelper.WriteLogToFile("AutoUpdate | Failed to retrieve remote version for fixing", LogHelper.LogType.Error); + LogHelper.WriteLogToFile("AutoUpdate | 修复版本时获取远程版本失败", LogHelper.LogType.Error); return false; } - LogHelper.WriteLogToFile($"AutoUpdate | Remote version for fixing: {remoteVersion}"); + + LogHelper.WriteLogToFile($"AutoUpdate | 修复版本远程版本: {remoteVersion}"); + // 无论版本是否为最新,都下载远程版本 - bool downloadResult = await DownloadSetupFileWithLineGroup(remoteVersion, group); + bool downloadResult = await DownloadSetupFile(remoteVersion, group); if (!downloadResult) { - LogHelper.WriteLogToFile("AutoUpdate | Failed to download update for fixing", LogHelper.LogType.Error); + LogHelper.WriteLogToFile("AutoUpdate | 修复版本时下载更新失败", LogHelper.LogType.Error); return false; } + // 执行安装,非静默模式 InstallNewVersionApp(remoteVersion, false); App.IsAppExitByUser = true; @@ -846,7 +1093,56 @@ namespace Ink_Canvas.Helpers } catch (Exception ex) { - LogHelper.WriteLogToFile($"AutoUpdate | Error in FixVersion: {ex.Message}", LogHelper.LogType.Error); + LogHelper.WriteLogToFile($"AutoUpdate | FixVersion错误: {ex.Message}", LogHelper.LogType.Error); + return false; + } + } + + // 测试Windows 7 TLS连接的方法 + public static async Task TestWindows7TlsConnection() + { + try + { + // 检测是否为Windows 7 + var osVersion = Environment.OSVersion; + bool isWindows7 = osVersion.Version.Major == 6 && osVersion.Version.Minor == 1; + + if (!isWindows7) + { + LogHelper.WriteLogToFile("AutoUpdate | 当前系统不是Windows 7,跳过TLS连接测试", LogHelper.LogType.Info); + return true; // 非Windows 7系统直接返回成功 + } + + LogHelper.WriteLogToFile("AutoUpdate | 开始测试Windows 7 TLS连接..."); + + // 测试GitHub连接 + var testUrl = "https://github.com/InkCanvasForClass/community/raw/refs/heads/main/AutomaticUpdateVersionControl.txt"; + + using (var handler = new HttpClientHandler()) + { + handler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true; + + using (var client = new HttpClient(handler)) + { + client.Timeout = TimeSpan.FromSeconds(10); + var response = await client.GetAsync(testUrl); + + if (response.IsSuccessStatusCode) + { + LogHelper.WriteLogToFile("AutoUpdate | Windows 7 TLS连接测试成功"); + return true; + } + else + { + LogHelper.WriteLogToFile($"AutoUpdate | Windows 7 TLS连接测试失败,状态码: {response.StatusCode}", LogHelper.LogType.Error); + return false; + } + } + } + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"AutoUpdate | Windows 7 TLS连接测试异常: {ex.Message}", LogHelper.LogType.Error); return false; } } diff --git a/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherSettingsControl.xaml b/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherSettingsControl.xaml index 63deeaad..01e5c5db 100644 --- a/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherSettingsControl.xaml +++ b/Ink Canvas/Helpers/Plugins/BuiltIn/SuperLauncher/LauncherSettingsControl.xaml @@ -71,7 +71,7 @@ -