feat(更新窗体): 优化更新流程和窗体显示
- 添加进度条更新逻辑,确保进度显示准确 - 设置窗体位置到屏幕右下角并置顶显示 - 移除窗体边框,优化视觉效果 - 添加总文件数统计,完善下载进度显示 - 优化状态更新逻辑,确保UI实时刷新
This commit is contained in:
parent
2a339142ad
commit
52ce8400ba
2
Form1.Designer.cs
generated
2
Form1.Designer.cs
generated
@ -67,10 +67,12 @@
|
||||
this.Controls.Add(this.Status_Box);
|
||||
this.Controls.Add(this.Update_Pro);
|
||||
this.Controls.Add(this.Update_Text);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "Update";
|
||||
this.Text = "自动更新";
|
||||
this.TopMost = true;
|
||||
this.Load += new System.EventHandler(this.Update_Load);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
183
Form1.cs
183
Form1.cs
@ -38,6 +38,8 @@ namespace CheckDownload
|
||||
private Dictionary<string, (byte[] Data, string ExpectedMd5)> _downloadedFiles = new Dictionary<string, (byte[], string)>();
|
||||
/// <summary>已完成下载的文件数</summary>
|
||||
private int _completedFiles = 0;
|
||||
/// <summary>需要下载的总文件数</summary>
|
||||
private int _totalFilesToDownload = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数,初始化更新窗体
|
||||
@ -59,6 +61,49 @@ namespace CheckDownload
|
||||
Update_Pro.Step = 1; // 设置步进值
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新进度条值
|
||||
/// </summary>
|
||||
/// <param name="percentage">进度百分比(0-100)</param>
|
||||
private void UpdateProgressValue(int percentage)
|
||||
{
|
||||
// 确保百分比在有效范围内
|
||||
if (percentage < 0) percentage = 0;
|
||||
if (percentage > 100) percentage = 100;
|
||||
|
||||
// 在UI线程上更新进度条值
|
||||
if (this.InvokeRequired)
|
||||
{
|
||||
this.Invoke((MethodInvoker)delegate
|
||||
{
|
||||
// 确保进度条值不超出范围
|
||||
if (percentage >= Update_Pro.Minimum && percentage <= Update_Pro.Maximum)
|
||||
{
|
||||
Update_Pro.Value = percentage;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果超出范围,则设置为最大或最小值
|
||||
Update_Pro.Value = Math.Min(Math.Max(percentage, Update_Pro.Minimum), Update_Pro.Maximum);
|
||||
}
|
||||
// 添加Application.DoEvents()调用,确保消息队列被处理
|
||||
Application.DoEvents();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
if (percentage >= Update_Pro.Minimum && percentage <= Update_Pro.Maximum)
|
||||
{
|
||||
Update_Pro.Value = percentage;
|
||||
}
|
||||
else
|
||||
{
|
||||
Update_Pro.Value = Math.Min(Math.Max(percentage, Update_Pro.Minimum), Update_Pro.Maximum);
|
||||
}
|
||||
Application.DoEvents();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 窗体加载事件处理方法,启动更新流程
|
||||
/// </summary>
|
||||
@ -66,8 +111,27 @@ namespace CheckDownload
|
||||
/// <param name="e">事件参数</param>
|
||||
public async void Update_Load(object sender, EventArgs e)
|
||||
{
|
||||
// 设置窗体位置到屏幕右下角
|
||||
PositionFormToBottomRight();
|
||||
|
||||
await UpdateFile(); // 执行更新流程
|
||||
this.Close(); // 更新完成后关闭窗体
|
||||
// 注意:窗体关闭逻辑已移至UpdateFile方法中,确保显示完成消息后再关闭
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置窗体位置到屏幕右下角
|
||||
/// </summary>
|
||||
private void PositionFormToBottomRight()
|
||||
{
|
||||
// 获取当前屏幕的工作区域(排除任务栏等系统元素)
|
||||
Rectangle workingArea = Screen.GetWorkingArea(this);
|
||||
|
||||
// 计算窗体在右下角的位置
|
||||
int x = workingArea.Right - this.Width;
|
||||
int y = workingArea.Bottom - this.Height;
|
||||
|
||||
// 设置窗体位置
|
||||
this.Location = new Point(x, y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -78,31 +142,67 @@ namespace CheckDownload
|
||||
{
|
||||
try
|
||||
{
|
||||
// 读取本地MD5文件信息
|
||||
// 定义更新流程的总步骤数和当前步骤
|
||||
const int totalSteps = 6; // 总共6个主要步骤
|
||||
int currentStep = 0;
|
||||
|
||||
// 更新进度条初始状态
|
||||
UpdateProgressValue(0);
|
||||
|
||||
// 步骤1: 读取本地MD5文件信息
|
||||
UpdateStatus("读取本地MD5文件...");
|
||||
var localData = await ReadLocalMd5File();
|
||||
if (!ValidateLocalData(localData.Version, localData.Md5, localData.Data)) return;
|
||||
UpdateProgressValue(++currentStep * 100 / totalSteps); // 更新进度为16%
|
||||
|
||||
// 获取在线MD5文件信息
|
||||
// 步骤2: 获取在线MD5文件信息
|
||||
UpdateStatus("获取在线MD5文件信息...");
|
||||
var onlineData = await GetOnlineMd5File();
|
||||
if (!ValidateOnlineData(onlineData.Version, onlineData.Md5)) return;
|
||||
UpdateProgressValue(++currentStep * 100 / totalSteps); // 更新进度为33%
|
||||
|
||||
// 比较版本,判断是否需要更新
|
||||
if (!ShouldUpdate(localData.Version, onlineData.Version)) return;
|
||||
// 步骤3: 比较版本,判断是否需要更新
|
||||
UpdateStatus("比较版本信息...");
|
||||
if (!ShouldUpdate(localData.Version, onlineData.Version))
|
||||
{
|
||||
UpdateStatus("当前已是最新版本,无需更新");
|
||||
UpdateProgressValue(100); // 完成进度
|
||||
return;
|
||||
}
|
||||
UpdateProgressValue(++currentStep * 100 / totalSteps); // 更新进度为50%
|
||||
|
||||
// 下载在线MD5文件
|
||||
// 步骤4: 下载在线MD5文件
|
||||
UpdateStatus("下载在线MD5文件...");
|
||||
var onlineFileData = await DownloadOnlineMd5File();
|
||||
if (onlineFileData == null) return;
|
||||
UpdateProgressValue(++currentStep * 100 / totalSteps); // 更新进度为66%
|
||||
|
||||
// 比较文件差异
|
||||
// 步骤5: 比较文件差异
|
||||
UpdateStatus("比较文件差异...");
|
||||
var differences = CompareDataDifferences(localData.Data, onlineFileData);
|
||||
UpdateProgressValue(++currentStep * 100 / totalSteps); // 更新进度为83%
|
||||
|
||||
// 步骤6: 下载和更新文件
|
||||
if (differences.Count > 0)
|
||||
{
|
||||
// 下载需要更新的文件
|
||||
await DownloadUpdatedFiles(differences);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateStatus("无文件需要更新");
|
||||
}
|
||||
|
||||
// 替换本地MD5文件
|
||||
ReplaceLocalMd5File();
|
||||
UpdateProgressValue(100); // 完成进度
|
||||
|
||||
// 显示更新完成消息
|
||||
UpdateStatus("更新完成");
|
||||
|
||||
// 等待1秒后关闭窗体
|
||||
await Task.Delay(1000);
|
||||
this.Close();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -351,8 +451,12 @@ namespace CheckDownload
|
||||
// 重置下载状态
|
||||
_completedFiles = 0;
|
||||
_downloadedFiles.Clear();
|
||||
Update_Pro.Maximum = differences.Count;
|
||||
Update_Pro.Value = 0;
|
||||
|
||||
// 设置总文件数
|
||||
_totalFilesToDownload = differences.Count;
|
||||
|
||||
// 更新状态信息
|
||||
UpdateStatus($"开始下载更新文件,共{differences.Count}个文件...");
|
||||
|
||||
// 创建信号量控制并发下载数量
|
||||
var semaphore = new SemaphoreSlim(MaxConcurrentDownloads);
|
||||
@ -368,6 +472,7 @@ namespace CheckDownload
|
||||
await Task.WhenAll(downloadTasks);
|
||||
|
||||
// 所有文件下载完成后统一校验和保存
|
||||
UpdateStatus("所有文件下载完成,开始校验和保存...");
|
||||
VerifyAndSaveAllFiles();
|
||||
}
|
||||
|
||||
@ -399,7 +504,6 @@ namespace CheckDownload
|
||||
{
|
||||
// 更新状态显示当前下载进度
|
||||
int current = Interlocked.Increment(ref _completedFiles);
|
||||
UpdateStatus($"正在下载 ({Update_Pro.Value + 1}/{Update_Pro.Maximum}): {expectedMd5}");
|
||||
|
||||
// 下载文件到内存
|
||||
using (var client = new HttpClient())
|
||||
@ -436,6 +540,8 @@ namespace CheckDownload
|
||||
|
||||
// 创建失败文件列表
|
||||
var failedFiles = new List<string>();
|
||||
int processedCount = 0;
|
||||
int totalFiles = _downloadedFiles.Count;
|
||||
|
||||
foreach (var item in _downloadedFiles)
|
||||
{
|
||||
@ -445,6 +551,10 @@ namespace CheckDownload
|
||||
|
||||
try
|
||||
{
|
||||
// 更新状态信息
|
||||
processedCount++;
|
||||
UpdateStatus($"正在校验和保存文件 ({processedCount}/{totalFiles}): {relativePath}");
|
||||
|
||||
// 计算内存中数据的MD5
|
||||
string actualMd5;
|
||||
using (var md5 = MD5.Create())
|
||||
@ -465,6 +575,16 @@ namespace CheckDownload
|
||||
|
||||
// 保存文件
|
||||
File.WriteAllBytes(localPath, data);
|
||||
|
||||
// 更新进度条 - 从95%到98%
|
||||
// 确保即使在totalFiles为0的情况下也不会出现除零错误,并且百分比不会超过98
|
||||
int percentage = 95;
|
||||
if (totalFiles > 0)
|
||||
{
|
||||
// 计算进度时确保不会超过98%
|
||||
percentage = 95 + Math.Min(3, (int)(processedCount * 3.0 / totalFiles));
|
||||
}
|
||||
UpdateProgressValue(percentage);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -483,6 +603,10 @@ namespace CheckDownload
|
||||
{
|
||||
throw new Exception($"{failedFiles.Count}个文件校验失败");
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateStatus("所有文件校验和保存成功");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -547,14 +671,28 @@ namespace CheckDownload
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新进度条
|
||||
/// 更新文件下载进度
|
||||
/// </summary>
|
||||
private void UpdateProgress()
|
||||
{
|
||||
// 在UI线程上更新进度条值
|
||||
this.Invoke((MethodInvoker)delegate
|
||||
// 计算下载进度百分比,避免除零错误
|
||||
int percentage = 0;
|
||||
if (_totalFilesToDownload > 0)
|
||||
{
|
||||
Update_Pro.Value++;
|
||||
percentage = (int)(_completedFiles * 100.0 / _totalFilesToDownload);
|
||||
}
|
||||
|
||||
// 更新状态信息
|
||||
UpdateStatus($"正在下载文件 ({_completedFiles}/{_totalFilesToDownload})...");
|
||||
|
||||
// 在UI线程上更新进度条值
|
||||
this.BeginInvoke((MethodInvoker)delegate
|
||||
{
|
||||
// 在下载阶段,进度从83%到95%之间变化
|
||||
// 确保不会超过95%
|
||||
int overallPercentage = 83 + Math.Min(12, (int)(percentage * 12.0 / 100));
|
||||
// 使用UpdateProgressValue方法确保值在有效范围内
|
||||
UpdateProgressValue(overallPercentage);
|
||||
});
|
||||
}
|
||||
|
||||
@ -572,7 +710,7 @@ namespace CheckDownload
|
||||
}
|
||||
// 将下载的在线MD5文件移动到本地MD5文件位置
|
||||
File.Move(_onlineMd5File, LocalMd5File);
|
||||
UpdateStatus("已更新本地版本信息");
|
||||
UpdateStatus("更新完成");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -586,12 +724,25 @@ namespace CheckDownload
|
||||
/// <param name="message">要显示的状态信息</param>
|
||||
private void UpdateStatus(string message)
|
||||
{
|
||||
// 在UI线程上更新状态文本框
|
||||
// 使用Invoke而不是BeginInvoke,确保UI更新完成
|
||||
if (this.InvokeRequired)
|
||||
{
|
||||
this.Invoke((MethodInvoker)delegate
|
||||
{
|
||||
Status_Box.Text = message;
|
||||
// 立即刷新控件,确保状态实时显示
|
||||
Status_Box.Update();
|
||||
// 添加Application.DoEvents()调用,确保消息队列被处理
|
||||
Application.DoEvents();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Status_Box.Text = message;
|
||||
Status_Box.Update();
|
||||
Application.DoEvents();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算字符串的MD5值
|
||||
|
Loading…
x
Reference in New Issue
Block a user