CI / Go Backend (push) Canceled after 0s
初始化 monorepo: Go后端(7微服务) + Unity客户端(9模块) + 启动器 HTML5原型: Three.js 3D体素世界, Perlin噪声地形, 原版材质, 22种方块 Minecraft创造模式背包: 双栏布局, 拖拽移动物品, 方向性元件引脚 AI助搭策划文档 + 客户端/服务端骨架 + Docker Compose + CI
49 lines
1.9 KiB
C#
49 lines
1.9 KiB
C#
using System;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Threading;
|
|
|
|
namespace PCL.Core.App.Essentials;
|
|
|
|
public static class UpdateHelper
|
|
{
|
|
/// <summary>
|
|
/// 更新启动器(替换文件)
|
|
/// </summary>
|
|
/// <param name="source">用于替换的来源文件路径</param>
|
|
/// <param name="target">目标文件路径</param>
|
|
public static Exception? Replace(string source, string target)
|
|
{
|
|
var backup = $"{target}.bak.{DateTime.Now.ToString("yyyyMMddHHmmss", CultureInfo.InvariantCulture)}";
|
|
Exception? lastEx = null;
|
|
try
|
|
{
|
|
source = Path.GetFullPath(source);
|
|
target = Path.GetFullPath(target);
|
|
// 备份目标文件
|
|
File.Copy(target, backup);
|
|
if (!File.Exists(backup)) throw new FileNotFoundException("备份目标文件失败", backup);
|
|
// 删除原文件并等待文件删除事件
|
|
var watcher = new FileSystemWatcher(Basics.GetParentPathOrEmpty(target), Path.GetFileName(target));
|
|
var deletedEvent = new ManualResetEventSlim(false);
|
|
watcher.Deleted += (_, _) => deletedEvent.Set();
|
|
watcher.EnableRaisingEvents = true;
|
|
File.Delete(target);
|
|
if (!deletedEvent.Wait(TimeSpan.FromSeconds(3))) throw new TimeoutException("删除目标文件失败");
|
|
watcher.EnableRaisingEvents = false;
|
|
watcher.Dispose();
|
|
// 复制到目标文件
|
|
File.Copy(source, target);
|
|
if (!File.Exists(target)) throw new FileNotFoundException("复制到目标文件失败", target);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// 出错:恢复原文件并返回异常
|
|
if (File.Exists(backup) && !File.Exists(target)) File.Move(backup, target);
|
|
lastEx = ex;
|
|
}
|
|
if (File.Exists(backup)) File.Delete(backup); // 删除备份文件
|
|
return lastEx;
|
|
}
|
|
}
|