improve:自动更新
This commit is contained in:
@@ -517,280 +517,320 @@ namespace Ink_Canvas.Helpers
|
|||||||
private static async Task<bool> DownloadFile(string fileUrl, string destinationPath, Action<double, string> progressCallback = null)
|
private static async Task<bool> DownloadFile(string fileUrl, string destinationPath, Action<double, string> progressCallback = null)
|
||||||
{
|
{
|
||||||
LogHelper.WriteLogToFile($"AutoUpdate | 正在尝试下载: {fileUrl}");
|
LogHelper.WriteLogToFile($"AutoUpdate | 正在尝试下载: {fileUrl}");
|
||||||
// 检测是否为Windows 7
|
int maxRetry = 3;
|
||||||
var osVersion = Environment.OSVersion;
|
int retryCount = 0;
|
||||||
bool isWindows7 = osVersion.Version.Major == 6 && osVersion.Version.Minor == 1;
|
while (retryCount < maxRetry)
|
||||||
|
|
||||||
if (isWindows7)
|
|
||||||
{
|
{
|
||||||
// Windows 7使用特殊配置
|
try
|
||||||
using (var handler = new HttpClientHandler())
|
|
||||||
{
|
{
|
||||||
try
|
// 检测是否为Windows 7
|
||||||
|
var osVersion = Environment.OSVersion;
|
||||||
|
bool isWindows7 = osVersion.Version.Major == 6 && osVersion.Version.Minor == 1;
|
||||||
|
if (isWindows7)
|
||||||
{
|
{
|
||||||
// 配置HttpClientHandler以支持Windows 7
|
// Windows 7使用特殊配置
|
||||||
handler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true;
|
using (var handler = new HttpClientHandler())
|
||||||
|
|
||||||
using (HttpClient client = new HttpClient(handler))
|
|
||||||
{
|
{
|
||||||
client.Timeout = TimeSpan.FromMinutes(5);
|
try
|
||||||
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);
|
// 配置HttpClientHandler以支持Windows 7
|
||||||
}
|
handler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true;
|
||||||
|
|
||||||
var downloadTask = client.GetAsync(fileUrl, HttpCompletionOption.ResponseHeadersRead);
|
using (HttpClient client = new HttpClient(handler))
|
||||||
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];
|
client.Timeout = TimeSpan.FromMinutes(5);
|
||||||
long totalBytesRead = 0;
|
client.DefaultRequestHeaders.Add("User-Agent", "ICC-CE Auto Updater");
|
||||||
int bytesRead;
|
|
||||||
DateTime lastProgressUpdate = DateTime.Now;
|
|
||||||
|
|
||||||
var downloadTimeoutTask = Task.Delay(TimeSpan.FromSeconds(60));
|
LogHelper.WriteLogToFile($"AutoUpdate | 开始下载: {fileUrl}");
|
||||||
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)
|
string tempFilePath = destinationPath + ".tmp";
|
||||||
{
|
|
||||||
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)");
|
|
||||||
progressCallback?.Invoke(percentage, $"下载中: {percentage:F1}%");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LogHelper.WriteLogToFile($"AutoUpdate | 已下载: {(totalBytesRead / 1024.0 / 1024.0):F2} MB");
|
|
||||||
progressCallback?.Invoke(0, $"已下载: {(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)
|
string directory = Path.GetDirectoryName(destinationPath);
|
||||||
|
if (!Directory.Exists(directory))
|
||||||
{
|
{
|
||||||
LogHelper.WriteLogToFile($"AutoUpdate | 下载超时(60秒无数据传输)", LogHelper.LogType.Error);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool downloadCompleted = await readTask;
|
HttpResponseMessage response = await downloadTask;
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | HTTP响应状态: {response.StatusCode}");
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
if (downloadCompleted)
|
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))
|
||||||
{
|
{
|
||||||
LogHelper.WriteLogToFile($"AutoUpdate | 下载完成: {(totalBytesRead / 1024.0 / 1024.0):F2} MB");
|
using (var downloadStream = await response.Content.ReadAsStreamAsync())
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
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)");
|
||||||
|
progressCallback?.Invoke(percentage, $"下载中: {percentage:F1}%");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 已下载: {(totalBytesRead / 1024.0 / 1024.0):F2} MB");
|
||||||
|
progressCallback?.Invoke(0, $"已下载: {(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)
|
||||||
{
|
{
|
||||||
double percentage = (double)totalBytesRead / totalBytes.Value * 100;
|
LogHelper.WriteLogToFile($"AutoUpdate | 下载超时(60秒无数据传输)", LogHelper.LogType.Error);
|
||||||
LogHelper.WriteLogToFile($"AutoUpdate | 下载进度: {percentage:F1}% ({(totalBytesRead / 1024.0 / 1024.0):F2} MB / {(totalBytes.Value / 1024.0 / 1024.0):F2} MB)");
|
return false;
|
||||||
progressCallback?.Invoke(percentage, $"下载中: {percentage:F1}%");
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
bool downloadCompleted = await readTask;
|
||||||
|
|
||||||
|
if (downloadCompleted)
|
||||||
{
|
{
|
||||||
LogHelper.WriteLogToFile($"AutoUpdate | 已下载: {(totalBytesRead / 1024.0 / 1024.0):F2} MB");
|
LogHelper.WriteLogToFile($"AutoUpdate | 下载完成: {(totalBytesRead / 1024.0 / 1024.0):F2} MB");
|
||||||
progressCallback?.Invoke(0, $"已下载: {(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)
|
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 | 下载超时(60秒无数据传输)", LogHelper.LogType.Error);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool downloadCompleted = await readTask;
|
HttpResponseMessage response = await downloadTask;
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | HTTP响应状态: {response.StatusCode}");
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
if (downloadCompleted)
|
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))
|
||||||
{
|
{
|
||||||
LogHelper.WriteLogToFile($"AutoUpdate | 下载完成: {(totalBytesRead / 1024.0 / 1024.0):F2} MB");
|
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)");
|
||||||
|
progressCallback?.Invoke(percentage, $"下载中: {percentage:F1}%");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 已下载: {(totalBytesRead / 1024.0 / 1024.0):F2} MB");
|
||||||
|
progressCallback?.Invoke(0, $"已下载: {(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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (File.Exists(tempFilePath))
|
try
|
||||||
{
|
|
||||||
if (File.Exists(destinationPath))
|
|
||||||
{
|
{
|
||||||
File.Delete(destinationPath);
|
string tempFilePath = destinationPath + ".tmp";
|
||||||
|
if (File.Exists(tempFilePath))
|
||||||
|
{
|
||||||
|
File.Delete(tempFilePath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
catch { }
|
||||||
|
|
||||||
File.Move(tempFilePath, destinationPath);
|
return false;
|
||||||
LogHelper.WriteLogToFile($"AutoUpdate | 文件保存到: {destinationPath}");
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (HttpRequestException ex)
|
||||||
|
{
|
||||||
|
retryCount++;
|
||||||
|
if (retryCount >= maxRetry)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 下载失败,已重试{retryCount}次: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
progressCallback?.Invoke(0, $"下载失败,已重试{retryCount}次: {ex.Message}");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
catch (HttpRequestException ex)
|
else
|
||||||
{
|
{
|
||||||
LogHelper.WriteLogToFile($"AutoUpdate | HTTP请求错误: {ex.Message}", LogHelper.LogType.Error);
|
LogHelper.WriteLogToFile($"AutoUpdate | 网络异常,{15 * retryCount}s后第{retryCount}次重试: {ex.Message}", LogHelper.LogType.Warning);
|
||||||
|
progressCallback?.Invoke(0, $"网络异常,{15 * retryCount}s后第{retryCount}次重试...");
|
||||||
|
await Task.Delay(15000);
|
||||||
}
|
}
|
||||||
catch (TaskCanceledException ex)
|
}
|
||||||
|
catch (IOException ex)
|
||||||
|
{
|
||||||
|
retryCount++;
|
||||||
|
if (retryCount >= maxRetry)
|
||||||
{
|
{
|
||||||
LogHelper.WriteLogToFile($"AutoUpdate | 下载超时: {ex.Message}", LogHelper.LogType.Error);
|
LogHelper.WriteLogToFile($"AutoUpdate | IO异常,已重试{retryCount}次: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
progressCallback?.Invoke(0, $"IO异常,已重试{retryCount}次: {ex.Message}");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
else
|
||||||
{
|
{
|
||||||
LogHelper.WriteLogToFile($"AutoUpdate | 下载文件时出错: {ex.Message}", LogHelper.LogType.Error);
|
LogHelper.WriteLogToFile($"AutoUpdate | IO异常,{15 * retryCount}s后第{retryCount}次重试: {ex.Message}", LogHelper.LogType.Warning);
|
||||||
if (ex.InnerException != null)
|
progressCallback?.Invoke(0, $"IO异常,{15 * retryCount}s后第{retryCount}次重试...");
|
||||||
{
|
await Task.Delay(15000);
|
||||||
LogHelper.WriteLogToFile($"AutoUpdate | 内部异常: {ex.InnerException.Message}", LogHelper.LogType.Error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string tempFilePath = destinationPath + ".tmp";
|
|
||||||
if (File.Exists(tempFilePath))
|
|
||||||
{
|
|
||||||
File.Delete(tempFilePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存下载状态
|
// 保存下载状态
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using System.Windows.Interop;
|
|||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Ink_Canvas
|
namespace Ink_Canvas
|
||||||
{
|
{
|
||||||
@@ -319,5 +320,115 @@ namespace Ink_Canvas
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<bool> DownloadAndInstallVersion(string version, string downloadUrl, CancellationToken token)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 开始下载版本: {version}, url: {downloadUrl}");
|
||||||
|
string updatesFolderPath = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "AutoUpdate");
|
||||||
|
if (!Directory.Exists(updatesFolderPath))
|
||||||
|
Directory.CreateDirectory(updatesFolderPath);
|
||||||
|
string zipFilePath = Path.Combine(updatesFolderPath, $"InkCanvasForClass.CE.{version}.zip");
|
||||||
|
string tmpFilePath = zipFilePath + ".tmp";
|
||||||
|
int maxRetry = 3;
|
||||||
|
int retryCount = 0;
|
||||||
|
while (retryCount < maxRetry)
|
||||||
|
{
|
||||||
|
long existingLength = 0;
|
||||||
|
if (File.Exists(tmpFilePath))
|
||||||
|
existingLength = new FileInfo(tmpFilePath).Length;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var client = new System.Net.Http.HttpClient())
|
||||||
|
{
|
||||||
|
client.Timeout = TimeSpan.FromMinutes(10);
|
||||||
|
client.DefaultRequestHeaders.Add("User-Agent", "ICC-CE Auto Updater");
|
||||||
|
if (existingLength > 0)
|
||||||
|
client.DefaultRequestHeaders.Range = new System.Net.Http.Headers.RangeHeaderValue(existingLength, null);
|
||||||
|
using (var response = await client.GetAsync(downloadUrl, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, token))
|
||||||
|
{
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
var totalBytes = response.Content.Headers.ContentLength.HasValue
|
||||||
|
? response.Content.Headers.ContentLength.Value + existingLength
|
||||||
|
: -1L;
|
||||||
|
using (var stream = await response.Content.ReadAsStreamAsync())
|
||||||
|
using (var fs = new FileStream(tmpFilePath, FileMode.Append, FileAccess.Write, FileShare.None))
|
||||||
|
{
|
||||||
|
byte[] buffer = new byte[8192];
|
||||||
|
long totalRead = existingLength;
|
||||||
|
int read;
|
||||||
|
var lastUpdate = DateTime.Now;
|
||||||
|
while ((read = await stream.ReadAsync(buffer, 0, buffer.Length, token)) > 0)
|
||||||
|
{
|
||||||
|
token.ThrowIfCancellationRequested();
|
||||||
|
await fs.WriteAsync(buffer, 0, read, token);
|
||||||
|
totalRead += read;
|
||||||
|
if ((DateTime.Now - lastUpdate).TotalMilliseconds > 200)
|
||||||
|
{
|
||||||
|
int percent = totalBytes > 0 ? (int)(totalRead * 100 / totalBytes) : 0;
|
||||||
|
Dispatcher.Invoke(() => {
|
||||||
|
DownloadProgressBar.Value = percent;
|
||||||
|
DownloadProgressText.Text = totalBytes > 0
|
||||||
|
? $"已下载 {totalRead / 1024 / 1024.0:F2} MB / {totalBytes / 1024 / 1024.0:F2} MB ({percent}%)"
|
||||||
|
: $"已下载 {totalRead / 1024 / 1024.0:F2} MB";
|
||||||
|
});
|
||||||
|
lastUpdate = DateTime.Now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Dispatcher.Invoke(() => {
|
||||||
|
DownloadProgressBar.Value = 100;
|
||||||
|
DownloadProgressText.Text = "下载完成,正在校验...";
|
||||||
|
});
|
||||||
|
await fs.FlushAsync(token);
|
||||||
|
}
|
||||||
|
if (File.Exists(zipFilePath)) File.Delete(zipFilePath);
|
||||||
|
File.Move(tmpFilePath, zipFilePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 下载完成后,调用现有安装流程
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 开始安装版本: {version}");
|
||||||
|
AutoUpdateHelper.InstallNewVersionApp(version, false);
|
||||||
|
App.IsAppExitByUser = true;
|
||||||
|
Application.Current.Dispatcher.Invoke(() => {
|
||||||
|
Application.Current.Shutdown();
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 用户取消下载", LogHelper.LogType.Info);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (Exception ex) when (ex is System.Net.Http.HttpRequestException || ex is IOException)
|
||||||
|
{
|
||||||
|
retryCount++;
|
||||||
|
if (retryCount >= maxRetry)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 下载失败,已重试{retryCount}次: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
Dispatcher.Invoke(() => {
|
||||||
|
DownloadProgressText.Text = $"下载失败,已重试{retryCount}次: {ex.Message}";
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 网络异常,{15 * retryCount}s后第{retryCount}次重试: {ex.Message}", LogHelper.LogType.Warning);
|
||||||
|
Dispatcher.Invoke(() => {
|
||||||
|
DownloadProgressText.Text = $"网络异常,{15 * retryCount}s后第{retryCount}次重试...";
|
||||||
|
});
|
||||||
|
await Task.Delay(15000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (File.Exists(tmpFilePath)) { /* 不删除,便于断点续传 */ }
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 下载或安装异常: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
Dispatcher.Invoke(() => {
|
||||||
|
DownloadProgressText.Text = $"下载异常: {ex.Message}";
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,73 +137,106 @@ namespace Ink_Canvas
|
|||||||
Directory.CreateDirectory(updatesFolderPath);
|
Directory.CreateDirectory(updatesFolderPath);
|
||||||
string zipFilePath = Path.Combine(updatesFolderPath, $"InkCanvasForClass.CE.{version}.zip");
|
string zipFilePath = Path.Combine(updatesFolderPath, $"InkCanvasForClass.CE.{version}.zip");
|
||||||
string tmpFilePath = zipFilePath + ".tmp";
|
string tmpFilePath = zipFilePath + ".tmp";
|
||||||
long existingLength = 0;
|
int maxRetry = 3;
|
||||||
if (File.Exists(tmpFilePath))
|
int retryCount = 0;
|
||||||
existingLength = new FileInfo(tmpFilePath).Length;
|
while (retryCount < maxRetry)
|
||||||
try
|
|
||||||
{
|
{
|
||||||
using (var client = new System.Net.Http.HttpClient())
|
long existingLength = 0;
|
||||||
|
if (File.Exists(tmpFilePath))
|
||||||
|
existingLength = new FileInfo(tmpFilePath).Length;
|
||||||
|
try
|
||||||
{
|
{
|
||||||
client.Timeout = TimeSpan.FromMinutes(10);
|
using (var client = new System.Net.Http.HttpClient())
|
||||||
client.DefaultRequestHeaders.Add("User-Agent", "ICC-CE Auto Updater");
|
|
||||||
if (existingLength > 0)
|
|
||||||
client.DefaultRequestHeaders.Range = new System.Net.Http.Headers.RangeHeaderValue(existingLength, null);
|
|
||||||
using (var response = await client.GetAsync(downloadUrl, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, token))
|
|
||||||
{
|
{
|
||||||
response.EnsureSuccessStatusCode();
|
client.Timeout = TimeSpan.FromMinutes(10);
|
||||||
var totalBytes = response.Content.Headers.ContentLength.HasValue
|
client.DefaultRequestHeaders.Add("User-Agent", "ICC-CE Auto Updater");
|
||||||
? response.Content.Headers.ContentLength.Value + existingLength
|
if (existingLength > 0)
|
||||||
: -1L;
|
client.DefaultRequestHeaders.Range = new System.Net.Http.Headers.RangeHeaderValue(existingLength, null);
|
||||||
using (var stream = await response.Content.ReadAsStreamAsync())
|
using (var response = await client.GetAsync(downloadUrl, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, token))
|
||||||
using (var fs = new FileStream(tmpFilePath, FileMode.Append, FileAccess.Write, FileShare.None))
|
|
||||||
{
|
{
|
||||||
byte[] buffer = new byte[8192];
|
response.EnsureSuccessStatusCode();
|
||||||
long totalRead = existingLength;
|
var totalBytes = response.Content.Headers.ContentLength.HasValue
|
||||||
int read;
|
? response.Content.Headers.ContentLength.Value + existingLength
|
||||||
var lastUpdate = DateTime.Now;
|
: -1L;
|
||||||
while ((read = await stream.ReadAsync(buffer, 0, buffer.Length, token)) > 0)
|
using (var stream = await response.Content.ReadAsStreamAsync())
|
||||||
|
using (var fs = new FileStream(tmpFilePath, FileMode.Append, FileAccess.Write, FileShare.None))
|
||||||
{
|
{
|
||||||
token.ThrowIfCancellationRequested();
|
byte[] buffer = new byte[8192];
|
||||||
await fs.WriteAsync(buffer, 0, read, token);
|
long totalRead = existingLength;
|
||||||
totalRead += read;
|
int read;
|
||||||
if ((DateTime.Now - lastUpdate).TotalMilliseconds > 200)
|
var lastUpdate = DateTime.Now;
|
||||||
|
while ((read = await stream.ReadAsync(buffer, 0, buffer.Length, token)) > 0)
|
||||||
{
|
{
|
||||||
int percent = totalBytes > 0 ? (int)(totalRead * 100 / totalBytes) : 0;
|
token.ThrowIfCancellationRequested();
|
||||||
DownloadProgressBar.Value = percent;
|
await fs.WriteAsync(buffer, 0, read, token);
|
||||||
DownloadProgressText.Text = totalBytes > 0
|
totalRead += read;
|
||||||
? $"已下载 {totalRead / 1024 / 1024.0:F2} MB / {totalBytes / 1024 / 1024.0:F2} MB ({percent}%)"
|
if ((DateTime.Now - lastUpdate).TotalMilliseconds > 200)
|
||||||
: $"已下载 {totalRead / 1024 / 1024.0:F2} MB";
|
{
|
||||||
lastUpdate = DateTime.Now;
|
int percent = totalBytes > 0 ? (int)(totalRead * 100 / totalBytes) : 0;
|
||||||
|
Dispatcher.Invoke(() => {
|
||||||
|
DownloadProgressBar.Value = percent;
|
||||||
|
DownloadProgressText.Text = totalBytes > 0
|
||||||
|
? $"已下载 {totalRead / 1024 / 1024.0:F2} MB / {totalBytes / 1024 / 1024.0:F2} MB ({percent}%)"
|
||||||
|
: $"已下载 {totalRead / 1024 / 1024.0:F2} MB";
|
||||||
|
});
|
||||||
|
lastUpdate = DateTime.Now;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Dispatcher.Invoke(() => {
|
||||||
|
DownloadProgressBar.Value = 100;
|
||||||
|
DownloadProgressText.Text = "下载完成,正在校验...";
|
||||||
|
});
|
||||||
|
await fs.FlushAsync(token);
|
||||||
}
|
}
|
||||||
DownloadProgressBar.Value = 100;
|
if (File.Exists(zipFilePath)) File.Delete(zipFilePath);
|
||||||
DownloadProgressText.Text = "下载完成,正在校验...";
|
File.Move(tmpFilePath, zipFilePath);
|
||||||
await fs.FlushAsync(token);
|
|
||||||
}
|
}
|
||||||
if (File.Exists(zipFilePath)) File.Delete(zipFilePath);
|
}
|
||||||
File.Move(tmpFilePath, zipFilePath);
|
// 下载完成后,调用现有安装流程
|
||||||
|
LogHelper.WriteLogToFile($"HistoryRollback | 开始安装版本: {version}");
|
||||||
|
AutoUpdateHelper.InstallNewVersionApp(version, false);
|
||||||
|
App.IsAppExitByUser = true;
|
||||||
|
Application.Current.Dispatcher.Invoke(() => {
|
||||||
|
Application.Current.Shutdown();
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"HistoryRollback | 用户取消下载", LogHelper.LogType.Info);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (Exception ex) when (ex is System.Net.Http.HttpRequestException || ex is IOException)
|
||||||
|
{
|
||||||
|
retryCount++;
|
||||||
|
if (retryCount >= maxRetry)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"HistoryRollback | 下载失败,已重试{retryCount}次: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
Dispatcher.Invoke(() => {
|
||||||
|
DownloadProgressText.Text = $"下载失败,已重试{retryCount}次: {ex.Message}";
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"HistoryRollback | 网络异常,{15 * retryCount}s后第{retryCount}次重试: {ex.Message}", LogHelper.LogType.Warning);
|
||||||
|
Dispatcher.Invoke(() => {
|
||||||
|
DownloadProgressText.Text = $"网络异常,{15 * retryCount}s后第{retryCount}次重试...";
|
||||||
|
});
|
||||||
|
await Task.Delay(15000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 下载完成后,调用现有安装流程
|
catch (Exception ex)
|
||||||
LogHelper.WriteLogToFile($"HistoryRollback | 开始安装版本: {version}");
|
{
|
||||||
AutoUpdateHelper.InstallNewVersionApp(version, false);
|
if (File.Exists(tmpFilePath)) { /* 不删除,便于断点续传 */ }
|
||||||
App.IsAppExitByUser = true;
|
LogHelper.WriteLogToFile($"HistoryRollback | 下载或安装异常: {ex.Message}", LogHelper.LogType.Error);
|
||||||
Application.Current.Dispatcher.Invoke(() => {
|
Dispatcher.Invoke(() => {
|
||||||
Application.Current.Shutdown();
|
DownloadProgressText.Text = $"下载异常: {ex.Message}";
|
||||||
});
|
});
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
|
||||||
{
|
|
||||||
LogHelper.WriteLogToFile($"HistoryRollback | 用户取消下载", LogHelper.LogType.Info);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
if (File.Exists(tmpFilePath)) { /* 不删除,便于断点续传 */ }
|
|
||||||
LogHelper.WriteLogToFile($"HistoryRollback | 下载或安装异常: {ex.Message}", LogHelper.LogType.Error);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnClosing(CancelEventArgs e)
|
protected override void OnClosing(CancelEventArgs e)
|
||||||
|
|||||||
Reference in New Issue
Block a user