733 lines
36 KiB
C#
733 lines
36 KiB
C#
using System;
|
||
using System.Diagnostics;
|
||
using System.IO;
|
||
using System.Net.Http;
|
||
using System.Threading.Tasks;
|
||
using System.Reflection;
|
||
using System.Windows;
|
||
using System.Collections.ObjectModel;
|
||
using System.Linq;
|
||
using System.Windows.Controls;
|
||
using System.IO.Compression;
|
||
using System.Text;
|
||
|
||
namespace Ink_Canvas.Helpers
|
||
{
|
||
internal class AutoUpdateHelper
|
||
{
|
||
public static async Task<string> CheckForUpdates(string proxy = null)
|
||
{
|
||
try
|
||
{
|
||
string localVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Local version: {localVersion}");
|
||
|
||
string remoteAddress = proxy;
|
||
remoteAddress += "https://raw.githubusercontent.com/awesome-iwb/icc-ce/refs/heads/main/AutomaticUpdateVersionControl.txt";
|
||
string remoteVersion = await GetRemoteVersion(remoteAddress);
|
||
|
||
if (remoteVersion != null)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Remote version: {remoteVersion}");
|
||
Version local = new Version(localVersion);
|
||
Version remote = new Version(remoteVersion);
|
||
if (remote > local)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | New version available: {remoteVersion}");
|
||
return remoteVersion;
|
||
}
|
||
else
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Current version is up to date");
|
||
return null;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
LogHelper.WriteLogToFile("AutoUpdate | Failed to retrieve remote version.", LogHelper.LogType.Error);
|
||
return null;
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Error in CheckForUpdates: {ex.Message}", LogHelper.LogType.Error);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
public static async Task<string> GetRemoteVersion(string fileUrl)
|
||
{
|
||
using (HttpClient client = new HttpClient())
|
||
{
|
||
try
|
||
{
|
||
// Set a reasonable timeout
|
||
client.Timeout = TimeSpan.FromSeconds(15);
|
||
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Sending HTTP request to: {fileUrl}");
|
||
HttpResponseMessage response = await client.GetAsync(fileUrl);
|
||
|
||
LogHelper.WriteLogToFile($"AutoUpdate | HTTP response status: {response.StatusCode}");
|
||
response.EnsureSuccessStatusCode();
|
||
|
||
string content = await response.Content.ReadAsStringAsync();
|
||
// Trim any whitespace, newlines, etc.
|
||
content = content.Trim();
|
||
|
||
// If the content contains HTML (likely the GitHub view page instead of raw content),
|
||
// try to extract the version number
|
||
if (content.Contains("<html") || content.Contains("<!DOCTYPE"))
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Received HTML content instead of raw version number - trying to extract version");
|
||
// Try to extract version from GitHub page - look for text content in the file
|
||
int startPos = content.IndexOf("<table");
|
||
if (startPos > 0)
|
||
{
|
||
int endPos = content.IndexOf("</table>", startPos);
|
||
if (endPos > startPos)
|
||
{
|
||
string tableContent = content.Substring(startPos, endPos - startPos);
|
||
// Look for the version number pattern (like 1.2.3 or 1.2.3.4)
|
||
var match = System.Text.RegularExpressions.Regex.Match(tableContent, @"(\d+\.\d+\.\d+(\.\d+)?)");
|
||
if (match.Success)
|
||
{
|
||
content = match.Groups[1].Value;
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Extracted version from HTML: {content}");
|
||
}
|
||
else
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Could not extract version from HTML content");
|
||
return null;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Response content: {content}");
|
||
return content;
|
||
}
|
||
catch (HttpRequestException ex)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | HTTP request error: {ex.Message}", LogHelper.LogType.Error);
|
||
}
|
||
catch (TaskCanceledException ex)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Request timed out: {ex.Message}", LogHelper.LogType.Error);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Error: {ex.Message}", LogHelper.LogType.Error);
|
||
}
|
||
|
||
return null;
|
||
}
|
||
}
|
||
|
||
private static string updatesFolderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "AutoUpdate");
|
||
private static string statusFilePath = null;
|
||
|
||
public static async Task<bool> DownloadSetupFileAndSaveStatus(string version, string proxy = "")
|
||
{
|
||
try
|
||
{
|
||
statusFilePath = Path.Combine(updatesFolderPath, $"DownloadV{version}Status.txt");
|
||
|
||
if (File.Exists(statusFilePath) && File.ReadAllText(statusFilePath).Trim().ToLower() == "true")
|
||
{
|
||
LogHelper.WriteLogToFile("AutoUpdate | Setup file already downloaded.");
|
||
return true;
|
||
}
|
||
|
||
// Ensure update directory exists
|
||
if (!Directory.Exists(updatesFolderPath))
|
||
{
|
||
Directory.CreateDirectory(updatesFolderPath);
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Created updates directory: {updatesFolderPath}");
|
||
}
|
||
|
||
// Use the correct URL format for GitHub releases
|
||
string downloadUrl = $"{proxy}https://github.com/awesome-iwb/icc-ce/releases/download/{version}/InkCanvasForClass.CE.{version}.zip";
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Download URL: {downloadUrl}");
|
||
|
||
SaveDownloadStatus(false);
|
||
string zipFilePath = Path.Combine(updatesFolderPath, $"InkCanvasForClass.CE.{version}.zip");
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Target file path: {zipFilePath}");
|
||
|
||
bool downloadSuccess = await DownloadFile(downloadUrl, zipFilePath);
|
||
|
||
if (downloadSuccess)
|
||
{
|
||
SaveDownloadStatus(true);
|
||
LogHelper.WriteLogToFile("AutoUpdate | Setup file successfully downloaded.");
|
||
return true;
|
||
}
|
||
else
|
||
{
|
||
LogHelper.WriteLogToFile("AutoUpdate | Failed to download the update file.", LogHelper.LogType.Error);
|
||
return false;
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Error downloading update: {ex.Message}", LogHelper.LogType.Error);
|
||
if (ex.InnerException != null)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Inner exception: {ex.InnerException.Message}", LogHelper.LogType.Error);
|
||
}
|
||
|
||
SaveDownloadStatus(false);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
private static async Task<bool> DownloadFile(string fileUrl, string destinationPath)
|
||
{
|
||
using (HttpClient client = new HttpClient())
|
||
{
|
||
try
|
||
{
|
||
// Configure client
|
||
client.Timeout = TimeSpan.FromMinutes(5); // Longer timeout for downloading larger files
|
||
client.DefaultRequestHeaders.Add("User-Agent", "ICC-CE Auto Updater");
|
||
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Downloading from: {fileUrl}");
|
||
|
||
// 创建临时文件路径
|
||
string tempFilePath = destinationPath + ".tmp";
|
||
|
||
// 确保目标目录存在
|
||
string directory = Path.GetDirectoryName(destinationPath);
|
||
if (!Directory.Exists(directory))
|
||
{
|
||
Directory.CreateDirectory(directory);
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Created directory: {directory}");
|
||
}
|
||
|
||
// 删除可能存在的临时文件
|
||
if (File.Exists(tempFilePath))
|
||
{
|
||
File.Delete(tempFilePath);
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Deleted existing temp file");
|
||
}
|
||
|
||
// 使用流式下载而不是一次性加载到内存
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Starting download...");
|
||
|
||
// 获取响应但不读取内容
|
||
HttpResponseMessage response = await client.GetAsync(fileUrl, HttpCompletionOption.ResponseHeadersRead);
|
||
response.EnsureSuccessStatusCode();
|
||
|
||
// 获取文件大小(如果服务器提供)
|
||
long? totalBytes = response.Content.Headers.ContentLength;
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Expected file size: {(totalBytes.HasValue ? totalBytes.Value.ToString() : "unknown")} bytes");
|
||
|
||
// 使用流式方式下载文件
|
||
using (var contentStream = await response.Content.ReadAsStreamAsync())
|
||
using (var fileStream = new FileStream(tempFilePath, FileMode.Create, FileAccess.Write, FileShare.None, 8192, true))
|
||
{
|
||
byte[] buffer = new byte[8192];
|
||
int bytesRead;
|
||
long totalBytesRead = 0;
|
||
int progressPercent = 0;
|
||
|
||
while ((bytesRead = await contentStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
|
||
{
|
||
await fileStream.WriteAsync(buffer, 0, bytesRead);
|
||
|
||
totalBytesRead += bytesRead;
|
||
|
||
// 报告进度(每10%)
|
||
if (totalBytes.HasValue)
|
||
{
|
||
int newProgressPercent = (int)((totalBytesRead * 100) / totalBytes.Value);
|
||
if (newProgressPercent >= progressPercent + 10)
|
||
{
|
||
progressPercent = newProgressPercent;
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Download progress: {progressPercent}%");
|
||
}
|
||
}
|
||
}
|
||
|
||
// 确保所有数据都写入到文件
|
||
await fileStream.FlushAsync();
|
||
}
|
||
|
||
// 检查临时文件大小
|
||
if (new FileInfo(tempFilePath).Length == 0)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Downloaded file is empty", LogHelper.LogType.Error);
|
||
if (File.Exists(tempFilePath)) File.Delete(tempFilePath);
|
||
return false;
|
||
}
|
||
|
||
// 如果目标文件已存在,先删除
|
||
if (File.Exists(destinationPath))
|
||
{
|
||
File.Delete(destinationPath);
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Deleted existing destination file");
|
||
}
|
||
|
||
// 将临时文件移动到最终位置
|
||
File.Move(tempFilePath, destinationPath);
|
||
LogHelper.WriteLogToFile($"AutoUpdate | File saved to: {destinationPath}");
|
||
|
||
return true;
|
||
}
|
||
catch (HttpRequestException ex)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | HTTP request error: {ex.Message}", LogHelper.LogType.Error);
|
||
if (ex.InnerException != null)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Inner exception: {ex.InnerException.Message}", LogHelper.LogType.Error);
|
||
}
|
||
return false;
|
||
}
|
||
catch (TaskCanceledException ex)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Download timed out: {ex.Message}", LogHelper.LogType.Error);
|
||
return false;
|
||
}
|
||
catch (IOException ex)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | IO error while downloading: {ex.Message}", LogHelper.LogType.Error);
|
||
if (ex.InnerException != null)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Inner exception: {ex.InnerException.Message}", LogHelper.LogType.Error);
|
||
}
|
||
return false;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Error downloading file: {ex.Message}", LogHelper.LogType.Error);
|
||
if (ex.InnerException != null)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Inner exception: {ex.InnerException.Message}", LogHelper.LogType.Error);
|
||
}
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
|
||
private static void SaveDownloadStatus(bool isSuccess)
|
||
{
|
||
try
|
||
{
|
||
if (statusFilePath == null) return;
|
||
|
||
string directory = Path.GetDirectoryName(statusFilePath);
|
||
if (!Directory.Exists(directory))
|
||
{
|
||
Directory.CreateDirectory(directory);
|
||
}
|
||
|
||
File.WriteAllText(statusFilePath, isSuccess.ToString());
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Error saving download status: {ex.Message}", LogHelper.LogType.Error);
|
||
}
|
||
}
|
||
|
||
public static void InstallNewVersionApp(string version, bool isInSilence)
|
||
{
|
||
try
|
||
{
|
||
string zipFilePath = Path.Combine(updatesFolderPath, $"InkCanvasForClass.CE.{version}.zip");
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Checking for ZIP file: {zipFilePath}");
|
||
|
||
if (!File.Exists(zipFilePath))
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | ZIP file not found: {zipFilePath}", LogHelper.LogType.Error);
|
||
return;
|
||
}
|
||
|
||
// Verify ZIP file size and validity
|
||
FileInfo fileInfo = new FileInfo(zipFilePath);
|
||
if (fileInfo.Length == 0)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | ZIP file is empty, cannot continue", LogHelper.LogType.Error);
|
||
return;
|
||
}
|
||
LogHelper.WriteLogToFile($"AutoUpdate | ZIP file size: {fileInfo.Length} bytes");
|
||
|
||
// 获取当前应用程序路径和进程ID
|
||
string currentAppDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||
int currentProcessId = Process.GetCurrentProcess().Id;
|
||
string appPath = Assembly.GetExecutingAssembly().Location;
|
||
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Current application directory: {currentAppDir}");
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Current process ID: {currentProcessId}");
|
||
|
||
// 创建批处理文件来执行更新操作
|
||
string batchFilePath = Path.Combine(Path.GetTempPath(), "UpdateICC_" + Guid.NewGuid().ToString().Substring(0, 8) + ".bat");
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Creating update batch file: {batchFilePath}");
|
||
|
||
// 构建批处理文件内容
|
||
StringBuilder batchContent = new StringBuilder();
|
||
batchContent.AppendLine("@echo off");
|
||
|
||
// 使窗口隐藏(使用VBS脚本运行隐藏窗口)
|
||
batchContent.AppendLine("echo Set objShell = CreateObject(\"WScript.Shell\") > \"%temp%\\hideme.vbs\"");
|
||
batchContent.AppendLine("echo objShell.Run \"cmd /c \"\"\" ^& WScript.Arguments(0) ^& \"\"\"\", 0, True >> \"%temp%\\hideme.vbs\"");
|
||
batchContent.AppendLine($"echo Wscript.Sleep 100 >> \"%temp%\\hideme.vbs\"");
|
||
|
||
// 创建真正的更新批处理文件
|
||
string updateBatPath = Path.Combine(Path.GetTempPath(), "ICCUpdate_" + Guid.NewGuid().ToString().Substring(0, 8) + ".bat");
|
||
batchContent.AppendLine($"echo @echo off > \"{updateBatPath}\"");
|
||
|
||
// 写入等待进程退出的代码到更新批处理文件
|
||
batchContent.AppendLine($"echo set PROC_ID={currentProcessId} >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo :CHECK_PROCESS >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo tasklist /fi \"PID eq %PROC_ID%\" ^| find \"%PROC_ID%\" ^> nul >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo if %%ERRORLEVEL%% == 0 ( >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo timeout /t 1 /nobreak ^> nul >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo goto CHECK_PROCESS >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo ) >> \"{updateBatPath}\"");
|
||
|
||
// 应用程序已关闭,开始更新操作
|
||
batchContent.AppendLine($"echo echo Application closed, starting update process... >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo timeout /t 2 /nobreak ^> nul >> \"{updateBatPath}\"");
|
||
|
||
// 创建临时解压目录
|
||
string extractPath = Path.Combine(updatesFolderPath, $"Extract_{version}");
|
||
batchContent.AppendLine($"echo echo Extracting update files... >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo if exist \"{extractPath}\" rd /s /q \"{extractPath}\" >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo mkdir \"{extractPath}\" >> \"{updateBatPath}\"");
|
||
|
||
// PowerShell解压ZIP文件(因为批处理不直接支持ZIP解压)
|
||
batchContent.AppendLine($"echo powershell -command \"Expand-Archive -Path '{zipFilePath.Replace("'", "''")}' -DestinationPath '{extractPath.Replace("'", "''")}' -Force\" >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo if %%ERRORLEVEL%% neq 0 ( >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo goto ERROR_EXIT >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo ) >> \"{updateBatPath}\"");
|
||
|
||
// 复制文件到应用程序目录
|
||
batchContent.AppendLine($"echo echo Copying updated files to application directory... >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo xcopy /s /y /e \"{extractPath}\\*\" \"{currentAppDir}\\\" >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo if %%ERRORLEVEL%% neq 0 ( >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo goto ERROR_EXIT >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo ) >> \"{updateBatPath}\"");
|
||
|
||
// 清理临时文件
|
||
batchContent.AppendLine($"echo echo Cleaning up temporary files... >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo if exist \"{extractPath}\" rd /s /q \"{extractPath}\" >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo if exist \"{zipFilePath}\" del /f /q \"{zipFilePath}\" >> \"{updateBatPath}\"");
|
||
|
||
// 启动更新后的应用程序
|
||
batchContent.AppendLine($"echo echo Update completed successfully! >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo :: 检查应用程序是否已经在运行 >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo tasklist /FI \"IMAGENAME eq Ink Canvas.exe\" | find /i \"Ink Canvas.exe\" > nul >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo if %%ERRORLEVEL%% neq 0 ( >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo echo 启动应用程序... >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo start \"\" \"{appPath}\" >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo ) else ( >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo echo 应用程序已经在运行,不再重复启动 >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo ) >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo exit /b 0 >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo goto EXIT >> \"{updateBatPath}\"");
|
||
|
||
// 错误退出处理
|
||
batchContent.AppendLine($"echo :ERROR_EXIT >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo start \"\" cmd /c \"echo Update failed! ^& pause\" >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo exit /b 1 >> \"{updateBatPath}\"");
|
||
|
||
// 删除批处理文件自身
|
||
batchContent.AppendLine($"echo :EXIT >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo del \"{updateBatPath}\" >> \"{updateBatPath}\"");
|
||
batchContent.AppendLine($"echo exit >> \"{updateBatPath}\"");
|
||
|
||
// 使用VBS脚本执行更新批处理文件(隐藏窗口)
|
||
batchContent.AppendLine($"wscript \"%temp%\\hideme.vbs\" \"{updateBatPath}\"");
|
||
batchContent.AppendLine("del \"%temp%\\hideme.vbs\"");
|
||
batchContent.AppendLine("exit");
|
||
|
||
// 写入批处理文件
|
||
File.WriteAllText(batchFilePath, batchContent.ToString());
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Created update batch file");
|
||
|
||
// 启动批处理文件(隐藏窗口)
|
||
Process.Start(new ProcessStartInfo
|
||
{
|
||
FileName = batchFilePath,
|
||
CreateNoWindow = true,
|
||
UseShellExecute = true,
|
||
WindowStyle = ProcessWindowStyle.Hidden
|
||
});
|
||
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Started update batch process with hidden window");
|
||
|
||
// 应用程序将由用户手动关闭或由MainWindow中的代码关闭
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Error preparing update installation: {ex.Message}", LogHelper.LogType.Error);
|
||
if (ex.InnerException != null)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Inner exception: {ex.InnerException.Message}", LogHelper.LogType.Error);
|
||
}
|
||
}
|
||
}
|
||
|
||
private static bool CopyDirectory(string sourceDir, string destinationDir)
|
||
{
|
||
bool allCopiesSuccessful = true;
|
||
|
||
try
|
||
{
|
||
// 创建目标目录(如果不存在)
|
||
Directory.CreateDirectory(destinationDir);
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Created/verified destination directory: {destinationDir}");
|
||
|
||
// 复制所有文件
|
||
foreach (string filePath in Directory.GetFiles(sourceDir))
|
||
{
|
||
string fileName = Path.GetFileName(filePath);
|
||
string destPath = Path.Combine(destinationDir, fileName);
|
||
try
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Copying file: {fileName}");
|
||
|
||
// 如果目标文件存在,先删除
|
||
if (File.Exists(destPath))
|
||
{
|
||
File.Delete(destPath);
|
||
}
|
||
|
||
File.Copy(filePath, destPath);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
allCopiesSuccessful = false;
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Error copying file {fileName}: {ex.Message}", LogHelper.LogType.Error);
|
||
}
|
||
}
|
||
|
||
// 递归复制所有子目录
|
||
foreach (string subDirPath in Directory.GetDirectories(sourceDir))
|
||
{
|
||
string subDirName = Path.GetFileName(subDirPath);
|
||
string destSubDir = Path.Combine(destinationDir, subDirName);
|
||
|
||
bool subDirCopyResult = CopyDirectory(subDirPath, destSubDir);
|
||
if (!subDirCopyResult)
|
||
{
|
||
allCopiesSuccessful = false;
|
||
}
|
||
}
|
||
|
||
return allCopiesSuccessful;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Error copying directory {sourceDir}: {ex.Message}", LogHelper.LogType.Error);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
private static void RestartApplication()
|
||
{
|
||
try
|
||
{
|
||
string appPath = Assembly.GetExecutingAssembly().Location;
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Restarting application: {appPath}");
|
||
|
||
// Create a batch file to wait briefly and then start the application
|
||
// This allows the current process to fully exit before starting the new instance
|
||
string batchFilePath = Path.Combine(Path.GetTempPath(), "RestartICC_" + Guid.NewGuid().ToString().Substring(0, 8) + ".bat");
|
||
|
||
string batchContent =
|
||
"@echo off\r\n" +
|
||
"timeout /t 2 /nobreak >nul\r\n" +
|
||
":: 检查应用程序是否已经在运行\r\n" +
|
||
"tasklist /FI \"IMAGENAME eq Ink Canvas.exe\" | find /i \"Ink Canvas.exe\" > nul\r\n" +
|
||
"if %ERRORLEVEL% neq 0 (\r\n" +
|
||
" echo 启动应用程序...\r\n" +
|
||
$" start \"\" \"{appPath}\"\r\n" +
|
||
") else (\r\n" +
|
||
" echo 应用程序已经在运行,不再重复启动\r\n" +
|
||
")\r\n" +
|
||
"timeout /t 1 /nobreak >nul\r\n" +
|
||
"del \"%~f0\"\r\n" +
|
||
"exit\r\n"; // 确保批处理进程结束
|
||
|
||
File.WriteAllText(batchFilePath, batchContent);
|
||
|
||
// Start the batch file
|
||
Process.Start(new ProcessStartInfo
|
||
{
|
||
FileName = "cmd.exe",
|
||
Arguments = $"/c start \"\" \"{batchFilePath}\"",
|
||
CreateNoWindow = true,
|
||
UseShellExecute = false
|
||
});
|
||
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Created restart script at {batchFilePath}");
|
||
|
||
// Shutdown the application
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Shutting down application for restart");
|
||
Application.Current.Dispatcher.Invoke(() =>
|
||
{
|
||
Application.Current.Shutdown();
|
||
});
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Error restarting application: {ex.Message}", LogHelper.LogType.Error);
|
||
|
||
// Fallback direct restart approach
|
||
try
|
||
{
|
||
string appPath = Assembly.GetExecutingAssembly().Location;
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Attempting direct restart: {appPath}");
|
||
|
||
// 检查是否已有实例运行
|
||
Process[] processes = Process.GetProcessesByName("Ink Canvas");
|
||
if (processes.Length <= 1) // 只有当前进程
|
||
{
|
||
Process.Start(appPath);
|
||
}
|
||
else
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Application already running, not starting a new instance");
|
||
}
|
||
|
||
Application.Current.Dispatcher.Invoke(() =>
|
||
{
|
||
Application.Current.Shutdown();
|
||
});
|
||
}
|
||
catch (Exception fallbackEx)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Fallback restart also failed: {fallbackEx.Message}", LogHelper.LogType.Error);
|
||
}
|
||
}
|
||
}
|
||
|
||
private static void ExecuteCommandLine(string command)
|
||
{
|
||
try
|
||
{
|
||
ProcessStartInfo processStartInfo = new ProcessStartInfo
|
||
{
|
||
FileName = "cmd.exe",
|
||
Arguments = $"/c {command} & exit", // 添加exit确保cmd进程退出
|
||
RedirectStandardOutput = true,
|
||
RedirectStandardError = true,
|
||
UseShellExecute = false,
|
||
CreateNoWindow = true
|
||
};
|
||
|
||
using (Process process = new Process { StartInfo = processStartInfo })
|
||
{
|
||
process.Start();
|
||
// 设置一个超时时间
|
||
bool exited = process.WaitForExit(500); // 等待500毫秒
|
||
if (!exited)
|
||
{
|
||
// 不等待进程完成,让它在后台运行
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Command is running in background");
|
||
}
|
||
Application.Current.Shutdown();
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Error executing command: {ex.Message}", LogHelper.LogType.Error);
|
||
}
|
||
}
|
||
|
||
public static void DeleteUpdatesFolder()
|
||
{
|
||
try
|
||
{
|
||
if (Directory.Exists(updatesFolderPath))
|
||
{
|
||
// Try to delete all files first in case of locking issues
|
||
foreach (string file in Directory.GetFiles(updatesFolderPath, "*", SearchOption.AllDirectories))
|
||
{
|
||
try
|
||
{
|
||
File.Delete(file);
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Deleted file: {file}");
|
||
}
|
||
catch (Exception fileEx)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Could not delete file {file}: {fileEx.Message}", LogHelper.LogType.Warning);
|
||
}
|
||
}
|
||
|
||
// Then try to delete subdirectories
|
||
foreach (string dir in Directory.GetDirectories(updatesFolderPath))
|
||
{
|
||
try
|
||
{
|
||
Directory.Delete(dir, true);
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Deleted directory: {dir}");
|
||
}
|
||
catch (Exception dirEx)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Could not delete directory {dir}: {dirEx.Message}", LogHelper.LogType.Warning);
|
||
}
|
||
}
|
||
|
||
// Finally try to delete the main directory
|
||
try
|
||
{
|
||
Directory.Delete(updatesFolderPath, true);
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Deleted updates folder: {updatesFolderPath}");
|
||
}
|
||
catch (Exception mainDirEx)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Could not completely delete updates folder: {mainDirEx.Message}", LogHelper.LogType.Warning);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Updates folder does not exist: {updatesFolderPath}");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogHelper.WriteLogToFile($"AutoUpdate | Error deleting updates folder: {ex.Message}", LogHelper.LogType.Error);
|
||
}
|
||
}
|
||
}
|
||
|
||
internal class AutoUpdateWithSilenceTimeComboBox
|
||
{
|
||
public static ObservableCollection<string> Hours { get; set; } = new ObservableCollection<string>();
|
||
public static ObservableCollection<string> Minutes { get; set; } = new ObservableCollection<string>();
|
||
|
||
public static void InitializeAutoUpdateWithSilenceTimeComboBoxOptions(ComboBox startTimeComboBox, ComboBox endTimeComboBox)
|
||
{
|
||
for (int hour = 0; hour <= 23; ++hour)
|
||
{
|
||
Hours.Add(hour.ToString("00"));
|
||
}
|
||
for (int minute = 0; minute <= 59; minute += 20)
|
||
{
|
||
Minutes.Add(minute.ToString("00"));
|
||
}
|
||
startTimeComboBox.ItemsSource = Hours.SelectMany(h => Minutes.Select(m => $"{h}:{m}"));
|
||
endTimeComboBox.ItemsSource = Hours.SelectMany(h => Minutes.Select(m => $"{h}:{m}"));
|
||
}
|
||
|
||
public static bool CheckIsInSilencePeriod(string startTime, string endTime)
|
||
{
|
||
if (startTime == endTime) return true;
|
||
DateTime currentTime = DateTime.Now;
|
||
|
||
DateTime StartTime = DateTime.ParseExact(startTime, "HH:mm", null);
|
||
DateTime EndTime = DateTime.ParseExact(endTime, "HH:mm", null);
|
||
if (StartTime <= EndTime)
|
||
{ // 单日时间段
|
||
return currentTime >= StartTime && currentTime <= EndTime;
|
||
}
|
||
else
|
||
{ // 跨越两天的时间段
|
||
return currentTime >= StartTime || currentTime <= EndTime;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|