improve:自动更新
This commit is contained in:
+10
-4
@@ -678,7 +678,7 @@ namespace Ink_Canvas
|
||||
Application.Current.Dispatcher.Invoke(() => { }, DispatcherPriority.Render);
|
||||
}
|
||||
|
||||
System.Threading.Thread.Sleep(500);
|
||||
await Task.Delay(500);
|
||||
RootPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
|
||||
|
||||
LogHelper.NewLog(string.Format("Ink Canvas Starting (Version: {0})", Assembly.GetExecutingAssembly().GetName().Version));
|
||||
@@ -1011,7 +1011,7 @@ namespace Ink_Canvas
|
||||
mutex = new Mutex(true, mutexName, out bool tempRet);
|
||||
|
||||
// 额外等待一小段时间确保更新进程完全退出
|
||||
Thread.Sleep(1000);
|
||||
await Task.Delay(1000);
|
||||
LogHelper.WriteLogToFile("App | 特殊模式等待完成,继续启动");
|
||||
}
|
||||
|
||||
@@ -1124,7 +1124,7 @@ namespace Ink_Canvas
|
||||
}
|
||||
|
||||
// 心跳相关
|
||||
private static Timer heartbeatTimer;
|
||||
private static DispatcherTimer heartbeatTimer;
|
||||
private static DateTime lastHeartbeat = DateTime.Now;
|
||||
private static Timer watchdogTimer;
|
||||
private static bool isStartupComplete = false;
|
||||
@@ -1134,7 +1134,13 @@ namespace Ink_Canvas
|
||||
|
||||
private void StartHeartbeatMonitor()
|
||||
{
|
||||
heartbeatTimer = new Timer(_ => lastHeartbeat = DateTime.Now, null, 0, 1000);
|
||||
heartbeatTimer = new DispatcherTimer
|
||||
{
|
||||
Interval = TimeSpan.FromSeconds(1)
|
||||
};
|
||||
heartbeatTimer.Tick += (_, __) => lastHeartbeat = DateTime.Now;
|
||||
heartbeatTimer.Start();
|
||||
|
||||
watchdogTimer = new Timer(_ =>
|
||||
{
|
||||
if (!isStartupComplete && appStartupStartTime != DateTime.MinValue)
|
||||
|
||||
@@ -1431,7 +1431,7 @@ namespace Ink_Canvas.Helpers
|
||||
try
|
||||
{
|
||||
LogHelper.WriteLogToFile($"AutoUpdate | 开始解压ZIP文件到: {extractPath}");
|
||||
ZipFile.ExtractToDirectory(zipFilePath, extractPath);
|
||||
SafeZipExtractor.ExtractZipSafely(zipFilePath, extractPath, overwrite: true);
|
||||
LogHelper.WriteLogToFile("AutoUpdate | ZIP文件解压完成");
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -186,11 +186,11 @@ namespace Ink_Canvas.Helpers
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放GPU资源
|
||||
/// 释放GPU相关资源标记
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
_renderTarget?.Clear();
|
||||
|
||||
_isInitialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,9 +209,5 @@ namespace Ink_Canvas.Helpers
|
||||
|
||||
private readonly DrawingAttributes _drawingAttributes;
|
||||
|
||||
public static implicit operator Stroke(StrokeVisual v)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
|
||||
namespace Ink_Canvas.Helpers
|
||||
{
|
||||
public static class SafeZipExtractor
|
||||
{
|
||||
/// <param name="zipFilePath">ZIP 文件路径</param>
|
||||
/// <param name="extractPath">解压目标目录</param>
|
||||
/// <param name="overwrite">是否覆盖已存在文件</param>
|
||||
public static void ExtractZipSafely(string zipFilePath, string extractPath, bool overwrite = true)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(zipFilePath))
|
||||
throw new ArgumentNullException(nameof(zipFilePath));
|
||||
if (string.IsNullOrWhiteSpace(extractPath))
|
||||
throw new ArgumentNullException(nameof(extractPath));
|
||||
|
||||
var fullExtractPath = Path.GetFullPath(extractPath);
|
||||
Directory.CreateDirectory(fullExtractPath);
|
||||
|
||||
using (var zip = ZipFile.OpenRead(zipFilePath))
|
||||
{
|
||||
foreach (var entry in zip.Entries)
|
||||
{
|
||||
// 跳过空条目
|
||||
if (string.IsNullOrEmpty(entry.FullName))
|
||||
continue;
|
||||
|
||||
// 防止绝对路径和盘符前缀
|
||||
if (Path.IsPathRooted(entry.FullName))
|
||||
continue;
|
||||
|
||||
// 统一路径分隔符
|
||||
var normalized = entry.FullName.Replace('/', Path.DirectorySeparatorChar);
|
||||
|
||||
// 拒绝包含 .. 的路径,防止目录穿越
|
||||
if (normalized.Contains(".." + Path.DirectorySeparatorChar) ||
|
||||
normalized.StartsWith(".." + Path.DirectorySeparatorChar, StringComparison.Ordinal))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var destinationPath = Path.GetFullPath(
|
||||
Path.Combine(fullExtractPath, normalized));
|
||||
|
||||
// 再次确认仍然在目标目录下
|
||||
if (!destinationPath.StartsWith(fullExtractPath, StringComparison.OrdinalIgnoreCase))
|
||||
continue;
|
||||
|
||||
// 目录条目
|
||||
if (entry.FullName.EndsWith("/", StringComparison.Ordinal) ||
|
||||
entry.FullName.EndsWith("\\", StringComparison.Ordinal))
|
||||
{
|
||||
Directory.CreateDirectory(destinationPath);
|
||||
continue;
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(destinationPath) ?? fullExtractPath);
|
||||
|
||||
if (!overwrite && File.Exists(destinationPath))
|
||||
continue;
|
||||
|
||||
using (var input = entry.Open())
|
||||
using (var output = File.Create(destinationPath))
|
||||
{
|
||||
input.CopyTo(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -92,6 +92,11 @@ namespace Ink_Canvas.Helpers
|
||||
|
||||
public TimeMachineHistory Undo()
|
||||
{
|
||||
if (_currentIndex < 0 || _currentIndex >= _currentStrokeHistory.Count)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var item = _currentStrokeHistory[_currentIndex];
|
||||
item.StrokeHasBeenCleared = !item.StrokeHasBeenCleared;
|
||||
_currentIndex--;
|
||||
@@ -102,6 +107,11 @@ namespace Ink_Canvas.Helpers
|
||||
|
||||
public TimeMachineHistory Redo()
|
||||
{
|
||||
if (_currentStrokeHistory.Count == 0 || _currentIndex >= _currentStrokeHistory.Count - 1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var item = _currentStrokeHistory[++_currentIndex];
|
||||
item.StrokeHasBeenCleared = !item.StrokeHasBeenCleared;
|
||||
NotifyUndoRedoState();
|
||||
|
||||
@@ -730,7 +730,7 @@ namespace Ink_Canvas
|
||||
try
|
||||
{
|
||||
// 解压ZIP文件
|
||||
ZipFile.ExtractToDirectory(zipFilePath, tempDir);
|
||||
SafeZipExtractor.ExtractZipSafely(zipFilePath, tempDir, overwrite: true);
|
||||
|
||||
// 读取元数据文件
|
||||
string metadataFile = Path.Combine(tempDir, "metadata.txt");
|
||||
|
||||
Reference in New Issue
Block a user