@@ -15,16 +15,35 @@ namespace Ink_Canvas.Helpers
1515{
1616 internal class AutoUpdateHelper
1717 {
18- public static async Task < string > CheckForUpdates ( string proxy = null )
18+ // 定义超时时间为10秒
19+ private static readonly TimeSpan RequestTimeout = TimeSpan . FromSeconds ( 10 ) ;
20+
21+ public static async Task < string > CheckForUpdates ( string proxy = null , UpdateChannel channel = UpdateChannel . Release )
1922 {
2023 try
2124 {
2225 string localVersion = Assembly . GetExecutingAssembly ( ) . GetName ( ) . Version . ToString ( ) ;
2326 LogHelper . WriteLogToFile ( $ "AutoUpdate | Local version: { localVersion } ") ;
2427
2528 string remoteAddress = proxy ;
26- string primaryUrl = "https://raw.githubusercontent.com/InkCanvasForClass/community/refs/heads/main/AutomaticUpdateVersionControl.txt" ;
27- string fallbackUrl = "https://raw.bgithub.xyz/InkCanvasForClass/community/refs/heads/main/AutomaticUpdateVersionControl.txt" ;
29+
30+ // 根据通道选择URL
31+ string primaryUrl , fallbackUrl ;
32+
33+ if ( channel == UpdateChannel . Release )
34+ {
35+ // Release通道版本信息地址
36+ primaryUrl = "https://github.com/InkCanvasForClass/community/raw/refs/heads/beta/AutomaticUpdateVersionControl.txt" ;
37+ fallbackUrl = "https://bgithub.xyz/InkCanvasForClass/community/raw/refs/heads/main/AutomaticUpdateVersionControl.txt" ;
38+ }
39+ else
40+ {
41+ // Beta通道版本信息地址
42+ primaryUrl = "https://github.com/InkCanvasForClass/community-beta/raw/refs/heads/main/AutomaticUpdateVersionControl.txt" ;
43+ fallbackUrl = "https://bgithub.xyz/InkCanvasForClass/community-beta/raw/refs/heads/main/AutomaticUpdateVersionControl.txt" ;
44+ }
45+
46+ LogHelper . WriteLogToFile ( $ "AutoUpdate | Checking for updates on { channel } channel") ;
2847
2948 // 先尝试主地址
3049 remoteAddress += primaryUrl ;
@@ -72,19 +91,19 @@ public static async Task<string> GetRemoteVersion(string fileUrl)
7291 {
7392 try
7493 {
75- // Set a reasonable timeout
76- client . Timeout = TimeSpan . FromSeconds ( 10 ) ; // 减少超时时间以便更快切换到备用地址
94+ // 设置超时时间为10秒
95+ client . Timeout = RequestTimeout ;
7796
7897 LogHelper . WriteLogToFile ( $ "AutoUpdate | Sending HTTP request to: { fileUrl } ") ;
7998
8099 // 使用带超时的Task.WhenAny来确保请求不会无限期等待
81100 var downloadTask = client . GetAsync ( fileUrl ) ;
82- var timeoutTask = Task . Delay ( client . Timeout ) ;
101+ var timeoutTask = Task . Delay ( RequestTimeout ) ;
83102
84103 var completedTask = await Task . WhenAny ( downloadTask , timeoutTask ) ;
85104 if ( completedTask == timeoutTask )
86105 {
87- LogHelper . WriteLogToFile ( $ "AutoUpdate | Request timed out after { client . Timeout . TotalSeconds } seconds", LogHelper . LogType . Error ) ;
106+ LogHelper . WriteLogToFile ( $ "AutoUpdate | Request timed out after { RequestTimeout . TotalSeconds } seconds", LogHelper . LogType . Error ) ;
88107 return null ;
89108 }
90109
@@ -150,7 +169,7 @@ public static async Task<string> GetRemoteVersion(string fileUrl)
150169 private static string updatesFolderPath = Path . Combine ( Path . GetDirectoryName ( Assembly . GetExecutingAssembly ( ) . Location ) , "AutoUpdate" ) ;
151170 private static string statusFilePath = null ;
152171
153- public static async Task < bool > DownloadSetupFileAndSaveStatus ( string version , string proxy = "" )
172+ public static async Task < bool > DownloadSetupFileAndSaveStatus ( string version , string proxy = "" , UpdateChannel channel = UpdateChannel . Release )
154173 {
155174 try
156175 {
@@ -169,10 +188,21 @@ public static async Task<bool> DownloadSetupFileAndSaveStatus(string version, st
169188 LogHelper . WriteLogToFile ( $ "AutoUpdate | Created updates directory: { updatesFolderPath } ") ;
170189 }
171190
172- // 主下载地址
173- string primaryUrl = $ "{ proxy } https://github.com/InkCanvasForClass/community/releases/download/{ version } /InkCanvasForClass.CE.{ version } .zip";
174- // 备用下载地址
175- string fallbackUrl = $ "{ proxy } https://bgithub.xyz/InkCanvasForClass/community/releases/download/{ version } /InkCanvasForClass.CE.{ version } .zip";
191+ // 根据通道选择下载地址
192+ string primaryUrl , fallbackUrl ;
193+
194+ if ( channel == UpdateChannel . Release )
195+ {
196+ // Release通道下载地址
197+ primaryUrl = $ "{ proxy } https://github.com/InkCanvasForClass/community/releases/download/{ version } /InkCanvasForClass.CE.{ version } .zip";
198+ fallbackUrl = $ "{ proxy } https://bgithub.xyz/InkCanvasForClass/community/releases/download/{ version } /InkCanvasForClass.CE.{ version } .zip";
199+ }
200+ else
201+ {
202+ // Beta通道下载地址
203+ primaryUrl = $ "{ proxy } https://github.com/InkCanvasForClass/community-beta/releases/download/{ version } /InkCanvasForClass.CE.{ version } .zip";
204+ fallbackUrl = $ "{ proxy } https://bgithub.xyz/InkCanvasForClass/community-beta/releases/download/{ version } /InkCanvasForClass.CE.{ version } .zip";
205+ }
176206
177207 LogHelper . WriteLogToFile ( $ "AutoUpdate | Primary download URL: { primaryUrl } ") ;
178208
@@ -222,7 +252,7 @@ private static async Task<bool> DownloadFile(string fileUrl, string destinationP
222252 try
223253 {
224254 // Configure client
225- client . Timeout = TimeSpan . FromMinutes ( 5 ) ; // Longer timeout for downloading larger files
255+ client . Timeout = TimeSpan . FromMinutes ( 5 ) ; // 下载文件需要更长的超时时间
226256 client . DefaultRequestHeaders . Add ( "User-Agent" , "ICC-CE Auto Updater" ) ;
227257
228258 LogHelper . WriteLogToFile ( $ "AutoUpdate | Downloading from: { fileUrl } ") ;
@@ -239,7 +269,7 @@ private static async Task<bool> DownloadFile(string fileUrl, string destinationP
239269
240270 // 使用带超时的Task.WhenAny来确保请求不会无限期等待
241271 var downloadTask = client . GetAsync ( fileUrl , HttpCompletionOption . ResponseHeadersRead ) ;
242- var initialTimeoutTask = Task . Delay ( TimeSpan . FromSeconds ( 30 ) ) ; // 30秒内必须有响应
272+ var initialTimeoutTask = Task . Delay ( RequestTimeout ) ; // 使用全局定义的10秒超时
243273
244274 var completedTask = await Task . WhenAny ( downloadTask , initialTimeoutTask ) ;
245275 if ( completedTask == initialTimeoutTask )
@@ -769,6 +799,150 @@ public static void DeleteUpdatesFolder()
769799 LogHelper . WriteLogToFile ( $ "AutoUpdate | Error deleting updates folder: { ex . Message } ", LogHelper . LogType . Error ) ;
770800 }
771801 }
802+
803+ // 新增:版本修复方法,强制下载并安装指定通道的最新版本
804+ public static async Task < bool > FixVersion ( UpdateChannel channel = UpdateChannel . Release )
805+ {
806+ try
807+ {
808+ LogHelper . WriteLogToFile ( $ "AutoUpdate | Starting version fix for { channel } channel") ;
809+
810+ // 获取当前通道的最新版本
811+ string latestVersion = await CheckForUpdates ( null , channel ) ;
812+
813+ if ( string . IsNullOrEmpty ( latestVersion ) )
814+ {
815+ LogHelper . WriteLogToFile ( "AutoUpdate | No newer version found for fixing" , LogHelper . LogType . Warning ) ;
816+ return false ;
817+ }
818+
819+ // 下载最新版本
820+ bool downloadResult = await DownloadSetupFileAndSaveStatus ( latestVersion , "" , channel ) ;
821+
822+ if ( ! downloadResult )
823+ {
824+ LogHelper . WriteLogToFile ( "AutoUpdate | Failed to download update for fixing" , LogHelper . LogType . Error ) ;
825+ return false ;
826+ }
827+
828+ // 执行安装,非静默模式
829+ InstallNewVersionApp ( latestVersion , false ) ;
830+
831+ // 设置为用户主动退出,避免被看门狗判定为崩溃
832+ App . IsAppExitByUser = true ;
833+
834+ // 关闭应用程序
835+ Application . Current . Dispatcher . Invoke ( ( ) => {
836+ Application . Current . Shutdown ( ) ;
837+ } ) ;
838+
839+ return true ;
840+ }
841+ catch ( Exception ex )
842+ {
843+ LogHelper . WriteLogToFile ( $ "AutoUpdate | Error in FixVersion: { ex . Message } ", LogHelper . LogType . Error ) ;
844+ return false ;
845+ }
846+ }
847+
848+ // 获取更新日志
849+ public static async Task < string > GetUpdateLog ( UpdateChannel channel = UpdateChannel . Release )
850+ {
851+ try
852+ {
853+ string primaryUrl , fallbackUrl ;
854+
855+ if ( channel == UpdateChannel . Release )
856+ {
857+ // Release通道更新日志地址
858+ primaryUrl = "https://github.com/InkCanvasForClass/community/raw/refs/heads/beta/UpdateLog.txt" ;
859+ fallbackUrl = "https://bgithub.xyz/InkCanvasForClass/community/raw/refs/heads/main/UpdateLog.txt" ;
860+ }
861+ else
862+ {
863+ // Beta通道更新日志地址
864+ primaryUrl = "https://github.com/InkCanvasForClass/community-beta/raw/refs/heads/main/UpdateLog.txt" ;
865+ fallbackUrl = "https://bgithub.xyz/InkCanvasForClass/community-beta/raw/refs/heads/main/UpdateLog.txt" ;
866+ }
867+
868+ LogHelper . WriteLogToFile ( $ "AutoUpdate | Getting update log from { channel } channel") ;
869+
870+ // 先尝试主地址
871+ string updateLog = await GetRemoteContent ( primaryUrl ) ;
872+
873+ // 如果主地址失败,尝试备用地址
874+ if ( string . IsNullOrEmpty ( updateLog ) )
875+ {
876+ LogHelper . WriteLogToFile ( $ "AutoUpdate | Primary URL failed for update log, trying fallback URL") ;
877+ updateLog = await GetRemoteContent ( fallbackUrl ) ;
878+ }
879+
880+ if ( ! string . IsNullOrEmpty ( updateLog ) )
881+ {
882+ LogHelper . WriteLogToFile ( $ "AutoUpdate | Successfully retrieved update log") ;
883+ return updateLog ;
884+ }
885+ else
886+ {
887+ LogHelper . WriteLogToFile ( "AutoUpdate | Failed to retrieve update log from both URLs." , LogHelper . LogType . Error ) ;
888+ return $ "# 无法获取更新日志\n \n 无法从服务器获取更新日志信息,请检查网络连接后重试。";
889+ }
890+ }
891+ catch ( Exception ex )
892+ {
893+ LogHelper . WriteLogToFile ( $ "AutoUpdate | Error in GetUpdateLog: { ex . Message } ", LogHelper . LogType . Error ) ;
894+ return $ "# 获取更新日志时发生错误\n \n 错误信息: { ex . Message } ";
895+ }
896+ }
897+
898+ // 获取远程内容的通用方法
899+ private static async Task < string > GetRemoteContent ( string fileUrl )
900+ {
901+ using ( HttpClient client = new HttpClient ( ) )
902+ {
903+ try
904+ {
905+ // 设置超时时间为10秒
906+ client . Timeout = RequestTimeout ;
907+
908+ LogHelper . WriteLogToFile ( $ "AutoUpdate | Sending HTTP request to: { fileUrl } ") ;
909+
910+ // 使用带超时的Task.WhenAny来确保请求不会无限期等待
911+ var downloadTask = client . GetAsync ( fileUrl ) ;
912+ var timeoutTask = Task . Delay ( RequestTimeout ) ;
913+
914+ var completedTask = await Task . WhenAny ( downloadTask , timeoutTask ) ;
915+ if ( completedTask == timeoutTask )
916+ {
917+ LogHelper . WriteLogToFile ( $ "AutoUpdate | Request timed out after { RequestTimeout . TotalSeconds } seconds", LogHelper . LogType . Error ) ;
918+ return null ;
919+ }
920+
921+ // 请求完成,检查结果
922+ HttpResponseMessage response = await downloadTask ;
923+
924+ LogHelper . WriteLogToFile ( $ "AutoUpdate | HTTP response status: { response . StatusCode } ") ;
925+ response . EnsureSuccessStatusCode ( ) ;
926+
927+ string content = await response . Content . ReadAsStringAsync ( ) ;
928+ return content ;
929+ }
930+ catch ( HttpRequestException ex )
931+ {
932+ LogHelper . WriteLogToFile ( $ "AutoUpdate | HTTP request error: { ex . Message } ", LogHelper . LogType . Error ) ;
933+ }
934+ catch ( TaskCanceledException ex )
935+ {
936+ LogHelper . WriteLogToFile ( $ "AutoUpdate | Request timed out: { ex . Message } ", LogHelper . LogType . Error ) ;
937+ }
938+ catch ( Exception ex )
939+ {
940+ LogHelper . WriteLogToFile ( $ "AutoUpdate | Error: { ex . Message } ", LogHelper . LogType . Error ) ;
941+ }
942+
943+ return null ;
944+ }
945+ }
772946 }
773947
774948 internal class AutoUpdateWithSilenceTimeComboBox
0 commit comments