3 Commits

Author SHA1 Message Date
9ba1b33ca3 移除添加以管理员身份运行的兼容性,以防windows报毒 2025-07-02 15:03:53 +08:00
96cfa4be48 更换更新进度显示样式 2025-06-30 23:54:52 +08:00
a0245a8457 修复一些已知问题 2025-06-30 22:15:08 +08:00
4 changed files with 155 additions and 95 deletions

129
Form1.Designer.cs generated
View File

@@ -28,81 +28,66 @@
/// </summary> /// </summary>
private void InitializeComponent() private void InitializeComponent()
{ {
this.Update_Text = new System.Windows.Forms.Label(); this.Update_Pro = new System.Windows.Forms.ProgressBar();
this.Update_Pro = new System.Windows.Forms.ProgressBar(); this.Status_Box = new System.Windows.Forms.Label();
this.Status_Box = new System.Windows.Forms.Label(); this.Count_Box = new System.Windows.Forms.Label();
this.Count_Box = new System.Windows.Forms.Label(); this.Size_Box = new System.Windows.Forms.Label();
this.Size_Box = new System.Windows.Forms.Label(); this.SuspendLayout();
this.SuspendLayout(); //
// // Update_Pro
// Update_Text //
// this.Update_Pro.Location = new System.Drawing.Point(12, 36);
this.Update_Text.AutoSize = true; this.Update_Pro.Name = "Update_Pro";
this.Update_Text.Location = new System.Drawing.Point(12, 12); this.Update_Pro.Size = new System.Drawing.Size(339, 23);
this.Update_Text.Name = "Update_Text"; this.Update_Pro.TabIndex = 1;
this.Update_Text.Size = new System.Drawing.Size(59, 12); //
this.Update_Text.TabIndex = 0; // Status_Box
this.Update_Text.Text = "更新状态:"; //
// this.Status_Box.Location = new System.Drawing.Point(12, 12);
// Update_Pro this.Status_Box.Name = "Status_Box";
// this.Status_Box.Size = new System.Drawing.Size(148, 12);
this.Update_Pro.Location = new System.Drawing.Point(12, 36); this.Status_Box.TabIndex = 2;
this.Update_Pro.Name = "Update_Pro"; this.Status_Box.Text = "...";
this.Update_Pro.Size = new System.Drawing.Size(339, 23); //
this.Update_Pro.TabIndex = 1; // Count_Box
// //
// Status_Box this.Count_Box.Location = new System.Drawing.Point(296, 12);
// this.Count_Box.Name = "Count_Box";
this.Status_Box.AutoSize = false; this.Count_Box.Size = new System.Drawing.Size(55, 13);
this.Status_Box.Location = new System.Drawing.Point(72, 12); this.Count_Box.TabIndex = 3;
this.Status_Box.Name = "Status_Box"; this.Count_Box.TextAlign = System.Drawing.ContentAlignment.TopRight;
this.Status_Box.Size = new System.Drawing.Size(94, 12); //
this.Status_Box.TabIndex = 2; // Size_Box
this.Status_Box.Text = "..."; //
// this.Size_Box.Location = new System.Drawing.Point(166, 12);
// Count_Box this.Size_Box.Name = "Size_Box";
// this.Size_Box.Size = new System.Drawing.Size(130, 13);
this.Count_Box.Location = new System.Drawing.Point(296, 12); this.Size_Box.TabIndex = 4;
this.Count_Box.Name = "Count_Box"; this.Size_Box.TextAlign = System.Drawing.ContentAlignment.TopRight;
this.Count_Box.Size = new System.Drawing.Size(55, 13); //
this.Count_Box.TabIndex = 3; // Update
this.Count_Box.TextAlign = System.Drawing.ContentAlignment.TopRight; //
// this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
// Size_Box this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
// this.ClientSize = new System.Drawing.Size(363, 73);
this.Size_Box.Location = new System.Drawing.Point(166, 12); this.ControlBox = false;
this.Size_Box.Name = "Size_Box"; this.Controls.Add(this.Size_Box);
this.Size_Box.Size = new System.Drawing.Size(130, 13); this.Controls.Add(this.Count_Box);
this.Size_Box.TabIndex = 4; this.Controls.Add(this.Status_Box);
this.Size_Box.TextAlign = System.Drawing.ContentAlignment.TopRight; this.Controls.Add(this.Update_Pro);
// this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
// Update this.MaximizeBox = false;
// this.MinimizeBox = false;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.Name = "Update";
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ShowInTaskbar = false;
this.ClientSize = new System.Drawing.Size(363, 73); this.Text = "自动更新";
this.ControlBox = false; this.TopMost = true;
this.Controls.Add(this.Size_Box); this.Load += new System.EventHandler(this.Update_Load);
this.Controls.Add(this.Count_Box); this.ResumeLayout(false);
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.ShowInTaskbar = false;
this.Text = "自动更新";
this.TopMost = true;
this.Load += new System.EventHandler(this.Update_Load);
this.ResumeLayout(false);
this.PerformLayout();
} }
#endregion #endregion
private System.Windows.Forms.Label Update_Text;
private System.Windows.Forms.ProgressBar Update_Pro; private System.Windows.Forms.ProgressBar Update_Pro;
private System.Windows.Forms.Label Status_Box; private System.Windows.Forms.Label Status_Box;
private System.Windows.Forms.Label Count_Box; private System.Windows.Forms.Label Count_Box;

116
Form1.cs
View File

@@ -75,6 +75,13 @@ namespace CheckDownload
// 基准目录路径(用于文件更新的目标目录) // 基准目录路径(用于文件更新的目标目录)
private string _baseDirectory; private string _baseDirectory;
// === 新增: 用于显示整体下载大小与速度 ===
private long _totalDownloadedBytes = 0; // 已下载总字节数
private DateTime _downloadStartTime; // 下载开始时间
private DateTime _lastSpeedUpdateTime; // 上一次更新速度的时间
private readonly object _speedLock = new object(); // 锁,用于多线程更新 UI
private long _bytesSinceLastSpeedCalc = 0; // 距离上次速度计算新增的字节数
/// <summary> /// <summary>
/// 初始化窗体 /// 初始化窗体
/// </summary> /// </summary>
@@ -127,21 +134,13 @@ namespace CheckDownload
/// <param name="message">状态消息</param> /// <param name="message">状态消息</param>
private void UpdateStatus(string message) private void UpdateStatus(string message)
{ {
// 只保留冒号后的简短信息(一般是文件名);若无冒号则原样显示
string display = message;
int idx = message.LastIndexOf(':');
if (idx >= 0 && idx < message.Length - 1)
{
display = message.Substring(idx + 1).Trim();
}
if (this.InvokeRequired) if (this.InvokeRequired)
{ {
this.Invoke((MethodInvoker)delegate { Status_Box.Text = display; }); this.Invoke((MethodInvoker)delegate { Status_Box.Text = message; });
} }
else else
{ {
Status_Box.Text = display; Status_Box.Text = message;
} }
} }
@@ -270,6 +269,13 @@ namespace CheckDownload
_totalCount = orderedFileList.Count; _totalCount = orderedFileList.Count;
_completedCount = 0; _completedCount = 0;
_downloadedFiles.Clear(); _downloadedFiles.Clear();
// === 新增: 初始化速度统计 ===
_totalDownloadedBytes = 0;
_downloadStartTime = DateTime.UtcNow;
_lastSpeedUpdateTime = _downloadStartTime;
_bytesSinceLastSpeedCalc = 0;
var failedFiles = new ConcurrentDictionary<string, string>(); var failedFiles = new ConcurrentDictionary<string, string>();
await PerformDownloads(orderedFileList, failedFiles); await PerformDownloads(orderedFileList, failedFiles);
@@ -543,14 +549,20 @@ namespace CheckDownload
return true; return true;
} }
UpdateStatus($"{fileName}"); if (!string.IsNullOrWhiteSpace(fileName))
{
UpdateStatus($"下载:{fileName}");
}
UpdateCount($"{_completedCount + 1}/{_totalCount}"); UpdateCount($"{_completedCount + 1}/{_totalCount}");
if (await DownloadFileFromOneDrive(filePath, expectedMd5, tempFilePath)) if (await DownloadFileFromOneDrive(filePath, expectedMd5, tempFilePath))
{ {
return true; return true;
} }
UpdateStatus($"{fileName}"); if (!string.IsNullOrWhiteSpace(fileName))
{
UpdateStatus($"下载:{fileName}");
}
UpdateCount($"{_completedCount + 1}/{_totalCount}"); UpdateCount($"{_completedCount + 1}/{_totalCount}");
string ossKey = $"File/{expectedMd5}"; string ossKey = $"File/{expectedMd5}";
@@ -570,7 +582,10 @@ namespace CheckDownload
} }
catch (Exception ex) when (ex is OssException || ex is WebException) catch (Exception ex) when (ex is OssException || ex is WebException)
{ {
UpdateStatus($"{fileName}"); if (!string.IsNullOrWhiteSpace(fileName))
{
UpdateStatus($"下载:{fileName}");
}
UpdateCount($"{_completedCount + 1}/{_totalCount}"); UpdateCount($"{_completedCount + 1}/{_totalCount}");
UpdateSize(""); UpdateSize("");
string ossKey = $"File/{expectedMd5}"; string ossKey = $"File/{expectedMd5}";
@@ -578,7 +593,10 @@ namespace CheckDownload
} }
catch (Exception ex) catch (Exception ex)
{ {
UpdateStatus($"下载异常: {fileName} - {ex.Message}"); if (!string.IsNullOrWhiteSpace(fileName))
{
UpdateStatus($"下载异常: {fileName} - {ex.Message}");
}
return false; return false;
} }
} }
@@ -599,25 +617,47 @@ namespace CheckDownload
return false; return false;
} }
UpdateStatus($"检查已存在的临时文件: {fileName}"); if (!string.IsNullOrWhiteSpace(fileName))
{
UpdateStatus($"检查已存在的临时文件: {fileName}");
}
string actualMd5 = await Task.Run(() => CalculateMD5FromFile(tempFilePath)); string actualMd5 = await Task.Run(() => CalculateMD5FromFile(tempFilePath));
if (actualMd5.Equals(expectedMd5, StringComparison.OrdinalIgnoreCase)) if (actualMd5.Equals(expectedMd5, StringComparison.OrdinalIgnoreCase))
{ {
UpdateStatus($"临时文件完整,跳过下载: {fileName}"); if (!string.IsNullOrWhiteSpace(fileName))
{
UpdateStatus($"临时文件完整,跳过下载: {fileName}");
}
// === 新增: 将已存在的有效临时文件大小计入总下载量 ===
try
{
var fileInfo = new FileInfo(tempFilePath);
Interlocked.Add(ref _totalDownloadedBytes, fileInfo.Length);
}
catch
{
// 忽略获取文件大小的错误
}
return true; return true;
} }
else else
{ {
UpdateStatus($"临时文件不完整,重新下载: {fileName}"); if (!string.IsNullOrWhiteSpace(fileName))
{
UpdateStatus($"临时文件不完整,重新下载: {fileName}");
}
File.Delete(tempFilePath); File.Delete(tempFilePath);
return false; return false;
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
UpdateStatus($"检查临时文件时出错,将重新下载: {fileName} - {ex.Message}"); if (!string.IsNullOrWhiteSpace(fileName))
{
UpdateStatus($"检查临时文件时出错,将重新下载: {fileName} - {ex.Message}");
}
try try
{ {
if (File.Exists(tempFilePath)) if (File.Exists(tempFilePath))
@@ -1496,10 +1536,21 @@ namespace CheckDownload
{ {
await localStream.WriteAsync(buffer, 0, bytesRead); await localStream.WriteAsync(buffer, 0, bytesRead);
totalRead += bytesRead; totalRead += bytesRead;
if (totalBytes.HasValue)
// === 新增: 统计整体下载量 ===
Interlocked.Add(ref _totalDownloadedBytes, bytesRead);
Interlocked.Add(ref _bytesSinceLastSpeedCalc, bytesRead);
// === 修改: 显示整体下载进度和速度(每 500ms 更新一次,避免频繁刷新) ===
if (DateTime.UtcNow - _lastSpeedUpdateTime > TimeSpan.FromMilliseconds(500))
{ {
string progressText = $"{FormatBytes(totalRead)}/{FormatBytes(totalBytes.Value)}"; lock (_speedLock)
UpdateSize(progressText); {
if (DateTime.UtcNow - _lastSpeedUpdateTime > TimeSpan.FromMilliseconds(500))
{
UpdateOverallSize();
}
}
} }
} }
} }
@@ -1521,7 +1572,7 @@ namespace CheckDownload
dblSByte = bytes / 1024.0; dblSByte = bytes / 1024.0;
} }
} }
return $"{dblSByte:0.##}{suffixes[i]}"; return $"{dblSByte:0.0}{suffixes[i]}";
} }
/// <summary> /// <summary>
@@ -1715,5 +1766,26 @@ namespace CheckDownload
} }
catch { } catch { }
} }
// === 新增: 更新整体下载大小与速度 ===
private void UpdateOverallSize()
{
DateTime now = DateTime.UtcNow;
double intervalSeconds = (now - _lastSpeedUpdateTime).TotalSeconds;
if (intervalSeconds <= 0) intervalSeconds = 0.1; // 防止除零
// 读取并清零自上次计算以来的字节数
long intervalBytes = Interlocked.Exchange(ref _bytesSinceLastSpeedCalc, 0);
double bytesPerSec = intervalBytes / intervalSeconds;
long downloaded = Interlocked.Read(ref _totalDownloadedBytes);
string speedText = $"{FormatBytes((long)bytesPerSec)}/s";
string sizeText = $"{FormatBytes(downloaded)}({speedText})";
_lastSpeedUpdateTime = now;
UpdateSize(sizeText);
}
} }
} }

View File

@@ -32,7 +32,7 @@
## 用户界面 ## 用户界面
- **实时进度显示**:通过进度条、已完成数量/总数、下载速度等信息,清晰地展示更新进度。 - **实时进度显示**:通过进度条、已完成数量/总数以及 **已下载总量(实时速度)** 的形式(两者均保留一位小数,每 0.5 秒刷新),清晰地展示更新进度。
- **简洁的状态反馈**:界面只显示当前正在处理的文件名等核心信息,避免被冗长的日志刷屏。 - **简洁的状态反馈**:界面只显示当前正在处理的文件名等核心信息,避免被冗长的日志刷屏。
- **友好的错误提示**:当发生严重错误时,会弹出简明扼要的错误信息窗口,而不是难以理解的完整堆栈跟踪。 - **友好的错误提示**:当发生严重错误时,会弹出简明扼要的错误信息窗口,而不是难以理解的完整堆栈跟踪。
- **自动定位与退出**:窗体启动时会自动停靠在屏幕右下角,更新完成后会自动关闭,对用户干扰极小。 - **自动定位与退出**:窗体启动时会自动停靠在屏幕右下角,更新完成后会自动关闭,对用户干扰极小。
@@ -174,6 +174,7 @@
## 📝 版本历史 ## 📝 版本历史
### 最新版本特性 ### 最新版本特性
- ✅ 新增"已下载总量 + 实时下载速度"显示,速度与大小均保留一位小数,避免大文件下载时 UI 停滞误判。
- ✅ 添加7z自动解压功能 - ✅ 添加7z自动解压功能
- ✅ 支持解压后程序自动设置管理员权限 - ✅ 支持解压后程序自动设置管理员权限
- ✅ 优化多线程下载性能 - ✅ 优化多线程下载性能

View File

@@ -9,6 +9,8 @@
<package id="Microsoft.Bcl.AsyncInterfaces" version="9.0.6" targetFramework="net472" /> <package id="Microsoft.Bcl.AsyncInterfaces" version="9.0.6" targetFramework="net472" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net472" /> <package id="Newtonsoft.Json" version="13.0.3" targetFramework="net472" />
<package id="SevenZipExtractor" version="1.0.19" targetFramework="net472" /> <package id="SevenZipExtractor" version="1.0.19" targetFramework="net472" />
<package id="SevenZipSharp" version="0.64" targetFramework="net472" />
<package id="SevenZipSharp.Interop" version="19.1.0" targetFramework="net472" />
<package id="System.Buffers" version="4.5.1" targetFramework="net472" /> <package id="System.Buffers" version="4.5.1" targetFramework="net472" />
<package id="System.IO.Pipelines" version="9.0.6" targetFramework="net472" /> <package id="System.IO.Pipelines" version="9.0.6" targetFramework="net472" />
<package id="System.Memory" version="4.5.5" targetFramework="net472" /> <package id="System.Memory" version="4.5.5" targetFramework="net472" />