自身更新

This commit is contained in:
2025-07-19 17:58:38 +08:00
parent 848de6f3fa
commit 6d12a89c9c

138
Form1.cs
View File

@@ -91,6 +91,9 @@ namespace CheckDownload
private readonly object _speedLock = new object(); // 锁,用于多线程更新 UI
private long _bytesSinceLastSpeedCalc = 0; // 距离上次速度计算新增的字节数
// 更新锁文件路径
private string _updateLockFilePath;
/// <summary>
/// 初始化窗体
/// </summary>
@@ -104,6 +107,7 @@ namespace CheckDownload
_appName = Assembly.GetExecutingAssembly().GetName().Name;
_currentProcessId = Process.GetCurrentProcess().Id;
_baseDirectory = Application.StartupPath;
_updateLockFilePath = Path.Combine(_baseDirectory, "update.lock");
ConfigureProgressBar();
}
@@ -202,6 +206,26 @@ namespace CheckDownload
}
finally
{
// 删除更新锁文件,让批处理脚本知道程序已退出
CleanupLockFile();
}
}
/// <summary>
/// 清理更新锁文件
/// </summary>
private void CleanupLockFile()
{
try
{
if (!string.IsNullOrEmpty(_updateLockFilePath) && File.Exists(_updateLockFilePath))
{
File.Delete(_updateLockFilePath);
}
}
catch
{
// 忽略清理锁文件时的错误
}
}
@@ -1016,38 +1040,122 @@ namespace CheckDownload
{
string batchFilePath = Path.Combine(_baseDirectory, "update_files.bat");
string processId = Process.GetCurrentProcess().Id.ToString();
string processName = Process.GetCurrentProcess().ProcessName;
// 创建锁文件,程序退出前会删除它
File.WriteAllText(_updateLockFilePath, processId);
var batchContent = new StringBuilder();
batchContent.AppendLine("@echo off");
batchContent.AppendLine("chcp 65001 > nul");
batchContent.AppendLine(":check_process");
batchContent.AppendLine($"tasklist /FI \"PID eq {processId}\" 2>NUL | find /I \"{processId}\" >NUL");
batchContent.AppendLine("if %ERRORLEVEL% == 0 (");
batchContent.AppendLine(" timeout /t 1 /nobreak > NUL");
batchContent.AppendLine(" goto check_process");
batchContent.AppendLine("title Update Process");
// 简化的等待逻辑,避免复杂的计数器
batchContent.AppendLine("echo 等待程序退出...");
batchContent.AppendLine(":wait_loop");
// 优先检查锁文件
batchContent.AppendLine($"if not exist \"{_updateLockFilePath}\" goto process_check");
// 等待0.5秒
batchContent.AppendLine("ping 127.0.0.1 -n 1 -w 500 >nul");
batchContent.AppendLine("goto wait_loop");
batchContent.AppendLine(":process_check");
// 再次确认进程已退出
batchContent.AppendLine($"tasklist /FI \"PID eq {processId}\" 2>nul | find /I \"{processId}\" >nul");
batchContent.AppendLine("if %ERRORLEVEL% equ 0 (");
batchContent.AppendLine(" ping 127.0.0.1 -n 1 -w 500 >nul");
batchContent.AppendLine(" goto process_check");
batchContent.AppendLine(")");
batchContent.AppendLine("timeout /t 2 /nobreak > NUL");
// 额外等待确保完全退出
batchContent.AppendLine("ping 127.0.0.1 -n 1 -w 1000 >nul");
batchContent.AppendLine("echo 开始更新文件...");
// 简化的文件处理逻辑,避免复杂的标签
int fileIndex = 0;
foreach (var file in files)
{
batchContent.AppendLine($"del \"{file.original}\" /f /q");
string fileName = Path.GetFileName(file.original);
batchContent.AppendLine($"echo 处理文件: {fileName}");
// 检查新文件是否存在
batchContent.AppendLine($"if not exist \"{file.newFile}\" (");
batchContent.AppendLine($" echo 错误: 新文件不存在 - {fileName}");
batchContent.AppendLine($" goto file_{fileIndex}_end");
batchContent.AppendLine($")");
// 删除原文件(如果存在)
batchContent.AppendLine($"if exist \"{file.original}\" (");
batchContent.AppendLine($" echo 删除原文件: {fileName}");
batchContent.AppendLine($" del \"{file.original}\" /f /q");
batchContent.AppendLine($")");
// 复制新文件
batchContent.AppendLine($"echo 复制新文件: {fileName}");
batchContent.AppendLine($"copy /Y \"{file.newFile}\" \"{file.original}\"");
// 验证复制是否成功
batchContent.AppendLine($"if exist \"{file.original}\" (");
batchContent.AppendLine($" echo 成功更新: {fileName}");
batchContent.AppendLine($" del \"{file.newFile}\" /f /q");
batchContent.AppendLine($") else (");
batchContent.AppendLine($" echo 失败: 无法创建 {fileName}");
batchContent.AppendLine($")");
batchContent.AppendLine($":file_{fileIndex}_end");
fileIndex++;
}
// 清理工作
batchContent.AppendLine("echo 清理临时文件...");
// 删除锁文件
batchContent.AppendLine($"if exist \"{_updateLockFilePath}\" del \"{_updateLockFilePath}\" /f /q");
// 简化的清理逻辑
batchContent.AppendLine($"cd /d \"{_baseDirectory}\"");
batchContent.AppendLine("for %%f in (*.new) do del \"%%f\" /f /q");
batchContent.AppendLine("for %%f in (*.bak) do del \"%%f\" /f /q");
batchContent.AppendLine("echo 更新完成");
batchContent.AppendLine("ping 127.0.0.1 -n 1 -w 2000 >nul");
// 删除批处理脚本自身
batchContent.AppendLine("del \"%~f0\" /f /q");
batchContent.AppendLine("exit");
File.WriteAllText(batchFilePath, batchContent.ToString(), new UTF8Encoding(false));
// 使用Win7兼容的启动方式
var startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = $"/c \"{batchFilePath}\"",
CreateNoWindow = true,
UseShellExecute = false,
WindowStyle = ProcessWindowStyle.Hidden
FileName = batchFilePath,
CreateNoWindow = false, // Win7下设为false更稳定
UseShellExecute = true, // Win7下必须使用Shell执行
WindowStyle = ProcessWindowStyle.Minimized,
WorkingDirectory = _baseDirectory
};
Process.Start(startInfo);
try
{
Process.Start(startInfo);
}
catch (Exception)
{
// 如果上面的方式失败尝试直接用cmd执行
var fallbackStartInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = $"/c \"{batchFilePath}\"",
CreateNoWindow = true,
UseShellExecute = true,
WindowStyle = ProcessWindowStyle.Hidden,
WorkingDirectory = _baseDirectory
};
Process.Start(fallbackStartInfo);
}
UpdateStatus("已创建更新脚本,程序退出后将自动完成更新");
}
catch (Exception ex)
{