improve:自动更新
This commit is contained in:
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
xmlns:local="clr-namespace:Ink_Canvas"
|
xmlns:local="clr-namespace:Ink_Canvas"
|
||||||
xmlns:tb="http://www.hardcodet.net/taskbar"
|
xmlns:tb="http://www.hardcodet.net/taskbar"
|
||||||
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
|
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
|
||||||
StartupUri="MainWindow.xaml">
|
>
|
||||||
<Application.Resources>
|
<Application.Resources>
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
<Style TargetType="ui:ScrollViewerEx">
|
<Style TargetType="ui:ScrollViewerEx">
|
||||||
|
|||||||
+179
-15
@@ -482,32 +482,196 @@ namespace Ink_Canvas
|
|||||||
LogHelper.WriteLogToFile($"App | 使用频率: {DeviceIdentifier.GetUsageFrequency()}");
|
LogHelper.WriteLogToFile($"App | 使用频率: {DeviceIdentifier.GetUsageFrequency()}");
|
||||||
LogHelper.WriteLogToFile($"App | 更新优先级: {DeviceIdentifier.GetUpdatePriority()}");
|
LogHelper.WriteLogToFile($"App | 更新优先级: {DeviceIdentifier.GetUpdatePriority()}");
|
||||||
|
|
||||||
bool ret;
|
// 处理更新模式启动
|
||||||
mutex = new Mutex(true, "InkCanvasForClass CE", out ret);
|
bool isUpdateMode = AutoUpdateHelper.HandleUpdateModeStartup(e.Args);
|
||||||
|
|
||||||
if (!ret && !e.Args.Contains("-m")) //-m multiple
|
// 如果是更新模式,不显示主窗口但保持应用运行
|
||||||
|
if (isUpdateMode)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("App | 检测到更新模式,跳过主窗口显示,保持应用运行");
|
||||||
|
|
||||||
|
// 在更新模式下,保持应用程序运行直到更新完成
|
||||||
|
// 更新任务会在后台运行,完成后会自动启动新版本
|
||||||
|
// 设置一个定时器来检查更新是否完成
|
||||||
|
var updateCheckTimer = new Timer(async _ =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 检查是否有新的InkCanvasForClass.exe进程启动
|
||||||
|
var processes = Process.GetProcessesByName("InkCanvasForClass");
|
||||||
|
if (processes.Length > 1) // 如果有多个进程,说明新版本已启动
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("App | 检测到新版本已启动,退出更新进程");
|
||||||
|
IsAppExitByUser = true;
|
||||||
|
Application.Current.Dispatcher.Invoke(() =>
|
||||||
|
{
|
||||||
|
Application.Current.Shutdown();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"App | 更新检查定时器出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
}
|
||||||
|
}, null, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5));
|
||||||
|
|
||||||
|
// 在更新模式下,不创建主窗口,但保持应用程序运行
|
||||||
|
// 通过返回而不创建主窗口来实现
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否存在更新标记文件
|
||||||
|
string updateMarkerFile = Path.Combine(App.RootPath, "update_in_progress.tmp");
|
||||||
|
bool isUpdateInProgress = false;
|
||||||
|
|
||||||
|
// 检查是否以更新模式启动
|
||||||
|
isUpdateMode = e.Args.Contains("--update-mode");
|
||||||
|
|
||||||
|
if (File.Exists(updateMarkerFile))
|
||||||
{
|
{
|
||||||
LogHelper.NewLog("Detected existing instance");
|
|
||||||
MessageBox.Show("已有一个程序实例正在运行");
|
|
||||||
LogHelper.NewLog("Ink Canvas automatically closed");
|
|
||||||
IsAppExitByUser = true; // 多开时标记为用户主动退出
|
|
||||||
// 写入退出信号,确保看门狗不会重启
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
StartupCount.Reset();
|
string updateProcessIdStr = File.ReadAllText(updateMarkerFile).Trim();
|
||||||
File.WriteAllText(watchdogExitSignalFile, "exit");
|
if (int.TryParse(updateProcessIdStr, out int updateProcessId))
|
||||||
if (watchdogProcess != null && !watchdogProcess.HasExited)
|
|
||||||
{
|
{
|
||||||
watchdogProcess.Kill();
|
LogHelper.WriteLogToFile($"App | 检测到更新标记文件,更新进程ID: {updateProcessId}");
|
||||||
|
|
||||||
|
// 检查更新进程是否还在运行
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Process updateProcess = Process.GetProcessById(updateProcessId);
|
||||||
|
if (!updateProcess.HasExited)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("App | 更新进程仍在运行,等待更新完成");
|
||||||
|
isUpdateInProgress = true;
|
||||||
|
|
||||||
|
// 等待更新进程完成
|
||||||
|
int waitCount = 0;
|
||||||
|
const int maxWaitCount = 10; // 减少等待时间到10秒
|
||||||
|
|
||||||
|
while (waitCount < maxWaitCount && !updateProcess.HasExited)
|
||||||
|
{
|
||||||
|
Thread.Sleep(500); // 减少等待间隔到500ms
|
||||||
|
waitCount++;
|
||||||
|
LogHelper.WriteLogToFile($"App | 等待更新进程完成... ({waitCount}/{maxWaitCount})");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateProcess.HasExited)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("App | 更新进程已结束");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("App | 等待更新进程超时,强制清理", LogHelper.LogType.Warning);
|
||||||
|
// 超时后强制清理标记文件
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (File.Exists(updateMarkerFile))
|
||||||
|
{
|
||||||
|
File.Delete(updateMarkerFile);
|
||||||
|
LogHelper.WriteLogToFile("App | 强制清理更新标记文件");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"App | 强制清理更新标记文件失败: {ex.Message}", LogHelper.LogType.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("App | 更新进程已结束");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ArgumentException)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("App | 更新进程已不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 无论更新进程是否还在运行,都清理标记文件
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (File.Exists(updateMarkerFile))
|
||||||
|
{
|
||||||
|
File.Delete(updateMarkerFile);
|
||||||
|
LogHelper.WriteLogToFile("App | 清理更新标记文件");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"App | 清理更新标记文件失败: {ex.Message}", LogHelper.LogType.Warning);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch { }
|
catch (Exception ex)
|
||||||
Environment.Exit(0);
|
{
|
||||||
|
LogHelper.WriteLogToFile($"App | 读取更新标记文件失败: {ex.Message}", LogHelper.LogType.Warning);
|
||||||
|
// 如果读取失败,也尝试删除标记文件
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (File.Exists(updateMarkerFile))
|
||||||
|
{
|
||||||
|
File.Delete(updateMarkerFile);
|
||||||
|
LogHelper.WriteLogToFile("App | 清理损坏的更新标记文件");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是更新过程或更新模式,跳过Mutex检查
|
||||||
|
if (!isUpdateInProgress && !isUpdateMode)
|
||||||
|
{
|
||||||
|
bool ret;
|
||||||
|
mutex = new Mutex(true, "InkCanvasForClass CE", out ret);
|
||||||
|
|
||||||
|
if (!ret && !e.Args.Contains("-m")) //-m multiple
|
||||||
|
{
|
||||||
|
LogHelper.NewLog("Detected existing instance");
|
||||||
|
MessageBox.Show("已有一个程序实例正在运行");
|
||||||
|
LogHelper.NewLog("Ink Canvas automatically closed");
|
||||||
|
IsAppExitByUser = true; // 多开时标记为用户主动退出
|
||||||
|
// 写入退出信号,确保看门狗不会重启
|
||||||
|
try
|
||||||
|
{
|
||||||
|
StartupCount.Reset();
|
||||||
|
File.WriteAllText(watchdogExitSignalFile, "exit");
|
||||||
|
if (watchdogProcess != null && !watchdogProcess.HasExited)
|
||||||
|
{
|
||||||
|
watchdogProcess.Kill();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (isUpdateMode)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("App | 更新模式启动,跳过重复运行检测");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("App | 更新过程中,跳过重复运行检测");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 在更新过程中,创建一个临时的Mutex以避免其他检查出错
|
||||||
|
mutex = new Mutex(true, "InkCanvasForClass CE Update", out bool tempRet);
|
||||||
|
|
||||||
|
// 额外等待一小段时间确保更新进程完全退出
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
LogHelper.WriteLogToFile("App | 更新等待完成,继续启动");
|
||||||
}
|
}
|
||||||
|
|
||||||
_taskbar = (TaskbarIcon)FindResource("TaskbarTrayIcon");
|
_taskbar = (TaskbarIcon)FindResource("TaskbarTrayIcon");
|
||||||
|
|
||||||
StartArgs = e.Args;
|
StartArgs = e.Args;
|
||||||
|
|
||||||
|
// 在非更新模式下创建主窗口
|
||||||
|
var mainWindow = new MainWindow();
|
||||||
|
MainWindow = mainWindow;
|
||||||
|
mainWindow.Show();
|
||||||
|
|
||||||
// 新增:Office注册表检测
|
// 新增:Office注册表检测
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -49,5 +49,5 @@ using System.Windows;
|
|||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("1.7.8.0")]
|
[assembly: AssemblyVersion("1.7.8.1")]
|
||||||
[assembly: AssemblyFileVersion("1.7.8.0")]
|
[assembly: AssemblyFileVersion("1.7.8.1")]
|
||||||
|
|||||||
@@ -1134,7 +1134,7 @@ namespace Ink_Canvas.Helpers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 安装新版本应用
|
// 安装新版本应用 - 优化版本,不使用命令行
|
||||||
public static void InstallNewVersionApp(string version, bool isInSilence)
|
public static void InstallNewVersionApp(string version, bool isInSilence)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -1187,113 +1187,109 @@ namespace Ink_Canvas.Helpers
|
|||||||
LogHelper.WriteLogToFile($"AutoUpdate | ZIP文件大小: {fileInfo.Length} 字节");
|
LogHelper.WriteLogToFile($"AutoUpdate | ZIP文件大小: {fileInfo.Length} 字节");
|
||||||
|
|
||||||
string currentAppDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
string currentAppDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||||
int currentProcessId = Process.GetCurrentProcess().Id;
|
|
||||||
string appPath = Assembly.GetExecutingAssembly().Location;
|
string appPath = Assembly.GetExecutingAssembly().Location;
|
||||||
|
int currentProcessId = Process.GetCurrentProcess().Id;
|
||||||
|
|
||||||
LogHelper.WriteLogToFile($"AutoUpdate | 当前应用程序目录: {currentAppDir}");
|
LogHelper.WriteLogToFile($"AutoUpdate | 当前应用程序目录: {currentAppDir}");
|
||||||
LogHelper.WriteLogToFile($"AutoUpdate | 当前进程ID: {currentProcessId}");
|
LogHelper.WriteLogToFile($"AutoUpdate | 当前进程ID: {currentProcessId}");
|
||||||
LogHelper.WriteLogToFile($"AutoUpdate | 静默更新模式: {isInSilence}");
|
LogHelper.WriteLogToFile($"AutoUpdate | 静默更新模式: {isInSilence}");
|
||||||
|
|
||||||
string batchFilePath = Path.Combine(Path.GetTempPath(), "UpdateICC_" + Guid.NewGuid().ToString().Substring(0, 8) + ".bat");
|
// 创建解压目录
|
||||||
LogHelper.WriteLogToFile($"AutoUpdate | 创建更新批处理文件: {batchFilePath}");
|
|
||||||
|
|
||||||
StringBuilder batchContent = new StringBuilder();
|
|
||||||
batchContent.AppendLine("@echo off");
|
|
||||||
|
|
||||||
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 timeout /t 1 /nobreak > nul >> \"{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}");
|
string extractPath = Path.Combine(updatesFolderPath, $"Extract_{version}");
|
||||||
batchContent.AppendLine($"echo echo Extracting update files... >> \"{updateBatPath}\"");
|
if (Directory.Exists(extractPath))
|
||||||
batchContent.AppendLine($"echo if exist \"{extractPath}\" rd /s /q \"{extractPath}\" >> \"{updateBatPath}\"");
|
|
||||||
batchContent.AppendLine($"echo mkdir \"{extractPath}\" >> \"{updateBatPath}\"");
|
|
||||||
|
|
||||||
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}\"");
|
|
||||||
|
|
||||||
if (isInSilence)
|
|
||||||
{
|
{
|
||||||
batchContent.AppendLine($"echo echo 自动启动应用程序... >> \"{updateBatPath}\"");
|
try
|
||||||
batchContent.AppendLine($"echo start \"\" \"{appPath}\" >> \"{updateBatPath}\"");
|
{
|
||||||
}
|
Directory.Delete(extractPath, true);
|
||||||
else
|
LogHelper.WriteLogToFile($"AutoUpdate | 清理已存在的解压目录: {extractPath}");
|
||||||
{
|
}
|
||||||
batchContent.AppendLine($"echo taskkill /F /IM \"InkCanvasForClass.exe\" >nul 2>nul >> \"{updateBatPath}\"");
|
catch (Exception ex)
|
||||||
batchContent.AppendLine($"echo :: 检查应用程序是否已经在运行 >> \"{updateBatPath}\"");
|
{
|
||||||
batchContent.AppendLine($"echo tasklist /FI \"IMAGENAME eq InkCanvasForClass.exe\" | find /i \"InkCanvasForClass.exe\" > nul >> \"{updateBatPath}\"");
|
LogHelper.WriteLogToFile($"AutoUpdate | 清理解压目录失败: {ex.Message}", LogHelper.LogType.Warning);
|
||||||
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}\"");
|
try
|
||||||
batchContent.AppendLine($"echo goto EXIT >> \"{updateBatPath}\"");
|
|
||||||
|
|
||||||
if (isInSilence)
|
|
||||||
{
|
{
|
||||||
batchContent.AppendLine($"echo :ERROR_EXIT >> \"{updateBatPath}\"");
|
Directory.CreateDirectory(extractPath);
|
||||||
batchContent.AppendLine($"echo echo Update failed! >> \"%temp%\\icc_update_error.log\" >> \"{updateBatPath}\"");
|
LogHelper.WriteLogToFile($"AutoUpdate | 创建解压目录: {extractPath}");
|
||||||
batchContent.AppendLine($"echo exit /b 1 >> \"{updateBatPath}\"");
|
|
||||||
}
|
}
|
||||||
else
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
batchContent.AppendLine($"echo :ERROR_EXIT >> \"{updateBatPath}\"");
|
LogHelper.WriteLogToFile($"AutoUpdate | 创建解压目录失败: {ex.Message}", LogHelper.LogType.Error);
|
||||||
batchContent.AppendLine($"echo start \"\" cmd /c \"echo Update failed! ^& pause\" >> \"{updateBatPath}\"");
|
return;
|
||||||
batchContent.AppendLine($"echo exit /b 1 >> \"{updateBatPath}\"");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
batchContent.AppendLine($"echo :EXIT >> \"{updateBatPath}\"");
|
// 解压ZIP文件
|
||||||
batchContent.AppendLine($"echo del \"{updateBatPath}\" >> \"{updateBatPath}\"");
|
try
|
||||||
batchContent.AppendLine($"echo exit >> \"{updateBatPath}\"");
|
|
||||||
|
|
||||||
batchContent.AppendLine($"wscript \"%temp%\\hideme.vbs\" \"{updateBatPath}\"");
|
|
||||||
batchContent.AppendLine("del \"%temp%\\hideme.vbs\"");
|
|
||||||
batchContent.AppendLine("exit");
|
|
||||||
|
|
||||||
File.WriteAllText(batchFilePath, batchContent.ToString());
|
|
||||||
LogHelper.WriteLogToFile("AutoUpdate | 创建更新批处理文件完成");
|
|
||||||
|
|
||||||
Process.Start(new ProcessStartInfo
|
|
||||||
{
|
{
|
||||||
FileName = batchFilePath,
|
LogHelper.WriteLogToFile($"AutoUpdate | 开始解压ZIP文件到: {extractPath}");
|
||||||
CreateNoWindow = true,
|
ZipFile.ExtractToDirectory(zipFilePath, extractPath);
|
||||||
UseShellExecute = true,
|
LogHelper.WriteLogToFile("AutoUpdate | ZIP文件解压完成");
|
||||||
WindowStyle = ProcessWindowStyle.Hidden
|
}
|
||||||
});
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 解压ZIP文件失败: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
LogHelper.WriteLogToFile("AutoUpdate | 启动更新批处理进程(隐藏窗口)");
|
// 查找解压后的主程序文件
|
||||||
|
string newAppPath = null;
|
||||||
|
string[] possibleExeNames = { "InkCanvasForClass.exe", "Ink Canvas.exe", "InkCanvas.exe" };
|
||||||
|
|
||||||
|
foreach (string exeName in possibleExeNames)
|
||||||
|
{
|
||||||
|
string testPath = Path.Combine(extractPath, exeName);
|
||||||
|
if (File.Exists(testPath))
|
||||||
|
{
|
||||||
|
newAppPath = testPath;
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 找到新版本主程序: {newAppPath}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(newAppPath))
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("AutoUpdate | 在解压目录中未找到主程序文件", LogHelper.LogType.Error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 启动新版本进程
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 准备启动新版本进程: {newAppPath}");
|
||||||
|
|
||||||
|
// 启动新版本进程(以更新模式)
|
||||||
|
string arguments = $"--update-mode --old-process-id={currentProcessId} --extract-path=\"{extractPath}\" --target-path=\"{currentAppDir}\" --is-silence={isInSilence}";
|
||||||
|
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 启动新进程的命令行: {newAppPath} {arguments}");
|
||||||
|
|
||||||
|
ProcessStartInfo startInfo = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = newAppPath,
|
||||||
|
Arguments = arguments,
|
||||||
|
UseShellExecute = false,
|
||||||
|
CreateNoWindow = false
|
||||||
|
};
|
||||||
|
|
||||||
|
Process.Start(startInfo);
|
||||||
|
LogHelper.WriteLogToFile("AutoUpdate | 新版本进程启动命令已执行");
|
||||||
|
|
||||||
|
// 等待一小段时间确保新进程启动
|
||||||
|
Thread.Sleep(2000);
|
||||||
|
|
||||||
|
// 关闭当前旧软件进程
|
||||||
|
LogHelper.WriteLogToFile("AutoUpdate | 关闭当前旧软件进程");
|
||||||
|
App.IsAppExitByUser = true;
|
||||||
|
Application.Current.Dispatcher.Invoke(() =>
|
||||||
|
{
|
||||||
|
Application.Current.Shutdown();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 启动新版本进程时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -1305,6 +1301,407 @@ namespace Ink_Canvas.Helpers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理更新模式的启动参数
|
||||||
|
public static bool HandleUpdateModeStartup(string[] args)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 检查是否以更新模式启动
|
||||||
|
if (args.Contains("--update-mode"))
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("AutoUpdate | 检测到更新模式启动");
|
||||||
|
|
||||||
|
// 解析命令行参数
|
||||||
|
int oldProcessId = -1;
|
||||||
|
string extractPath = null;
|
||||||
|
string targetPath = null;
|
||||||
|
bool isSilence = false;
|
||||||
|
|
||||||
|
// 记录所有参数用于调试
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 接收到的命令行参数: {string.Join(" ", args)}");
|
||||||
|
|
||||||
|
for (int i = 0; i < args.Length; i++)
|
||||||
|
{
|
||||||
|
string arg = args[i];
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 处理参数 {i}: {arg}");
|
||||||
|
|
||||||
|
if (arg.StartsWith("--old-process-id="))
|
||||||
|
{
|
||||||
|
string processIdStr = arg.Substring("--old-process-id=".Length);
|
||||||
|
if (int.TryParse(processIdStr, out int pid))
|
||||||
|
{
|
||||||
|
oldProcessId = pid;
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 解析到老进程ID: {oldProcessId}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (arg.StartsWith("--extract-path="))
|
||||||
|
{
|
||||||
|
extractPath = arg.Substring("--extract-path=".Length).Trim('"');
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 解析到解压路径: {extractPath}");
|
||||||
|
}
|
||||||
|
else if (arg.StartsWith("--target-path="))
|
||||||
|
{
|
||||||
|
targetPath = arg.Substring("--target-path=".Length).Trim('"');
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 解析到目标路径: {targetPath}");
|
||||||
|
}
|
||||||
|
else if (arg.StartsWith("--is-silence="))
|
||||||
|
{
|
||||||
|
string silenceStr = arg.Substring("--is-silence=".Length);
|
||||||
|
if (bool.TryParse(silenceStr, out bool silence))
|
||||||
|
{
|
||||||
|
isSilence = silence;
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 解析到静默模式: {isSilence}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 更新参数 - 老进程ID: {oldProcessId}, 解压路径: {extractPath}, 目标路径: {targetPath}, 静默模式: {isSilence}");
|
||||||
|
|
||||||
|
if (oldProcessId > 0 && !string.IsNullOrEmpty(extractPath) && !string.IsNullOrEmpty(targetPath))
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 参数验证通过,启动更新任务");
|
||||||
|
// 启动更新任务
|
||||||
|
Task.Run(async () => await PerformUpdate(oldProcessId, extractPath, targetPath, isSilence));
|
||||||
|
return true; // 返回true表示是更新模式
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 参数验证失败 - 老进程ID: {oldProcessId}, 解压路径: {extractPath}, 目标路径: {targetPath}", LogHelper.LogType.Error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false; // 返回false表示不是更新模式
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 处理更新模式启动时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行实际的更新操作
|
||||||
|
private static async Task PerformUpdate(int oldProcessId, string extractPath, string targetPath, bool isSilence)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("AutoUpdate | 开始执行更新操作");
|
||||||
|
|
||||||
|
// 等待老进程完全退出
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 等待老进程 {oldProcessId} 退出");
|
||||||
|
int waitCount = 0;
|
||||||
|
const int maxWaitCount = 30; // 最多等待30秒
|
||||||
|
|
||||||
|
while (waitCount < maxWaitCount)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Process oldProcess = Process.GetProcessById(oldProcessId);
|
||||||
|
if (oldProcess.HasExited)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("AutoUpdate | 老进程已退出");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 老进程仍在运行,等待中... ({waitCount + 1}/{maxWaitCount})");
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
waitCount++;
|
||||||
|
}
|
||||||
|
catch (ArgumentException)
|
||||||
|
{
|
||||||
|
// 进程不存在,说明已经退出
|
||||||
|
LogHelper.WriteLogToFile("AutoUpdate | 老进程已退出(进程不存在)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (waitCount >= maxWaitCount)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("AutoUpdate | 等待老进程退出超时,尝试强制结束", LogHelper.LogType.Warning);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Process oldProcess = Process.GetProcessById(oldProcessId);
|
||||||
|
oldProcess.Kill();
|
||||||
|
Thread.Sleep(2000); // 等待进程完全结束
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 强制结束老进程失败: {ex.Message}", LogHelper.LogType.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保目标目录存在
|
||||||
|
if (!Directory.Exists(targetPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(targetPath);
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 创建目标目录: {targetPath}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 复制文件到目标目录
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 开始复制文件从 {extractPath} 到 {targetPath}");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 使用递归复制方法,支持重试机制
|
||||||
|
bool copySuccess = await CopyDirectoryWithRetryAsync(extractPath, targetPath);
|
||||||
|
if (copySuccess)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("AutoUpdate | 文件复制完成");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("AutoUpdate | 文件复制失败,部分文件可能无法覆盖", LogHelper.LogType.Error);
|
||||||
|
|
||||||
|
if (!isSilence)
|
||||||
|
{
|
||||||
|
MessageBox.Show("更新失败:部分文件无法覆盖,可能是文件正在使用中。\n请关闭所有相关程序后重试。", "更新失败", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 文件复制失败: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
|
||||||
|
if (!isSilence)
|
||||||
|
{
|
||||||
|
MessageBox.Show($"更新失败:文件复制时出错\n{ex.Message}", "更新失败", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清理临时文件
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("AutoUpdate | 清理临时文件");
|
||||||
|
|
||||||
|
// 删除解压目录
|
||||||
|
if (Directory.Exists(extractPath))
|
||||||
|
{
|
||||||
|
Directory.Delete(extractPath, true);
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 删除解压目录: {extractPath}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除ZIP文件
|
||||||
|
string zipFile = Path.Combine(updatesFolderPath, $"InkCanvasForClass.CE.*.zip");
|
||||||
|
string[] zipFiles = Directory.GetFiles(updatesFolderPath, "InkCanvasForClass.CE.*.zip");
|
||||||
|
foreach (string zip in zipFiles)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.Delete(zip);
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 删除ZIP文件: {zip}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 删除ZIP文件失败: {ex.Message}", LogHelper.LogType.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 清理临时文件时出错: {ex.Message}", LogHelper.LogType.Warning);
|
||||||
|
}
|
||||||
|
|
||||||
|
LogHelper.WriteLogToFile("AutoUpdate | 更新操作完成");
|
||||||
|
|
||||||
|
// 启动更新后的应用程序
|
||||||
|
string newAppPath = Path.Combine(targetPath, "InkCanvasForClass.exe");
|
||||||
|
if (File.Exists(newAppPath))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 准备启动更新后的应用程序: {newAppPath}");
|
||||||
|
|
||||||
|
// 获取当前更新进程ID
|
||||||
|
int currentUpdateProcessId = Process.GetCurrentProcess().Id;
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 当前更新进程ID: {currentUpdateProcessId}");
|
||||||
|
|
||||||
|
// 创建一个临时标记文件,用于新进程检测更新状态
|
||||||
|
string updateMarkerFile = Path.Combine(targetPath, "update_in_progress.tmp");
|
||||||
|
File.WriteAllText(updateMarkerFile, currentUpdateProcessId.ToString());
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 创建更新标记文件: {updateMarkerFile}");
|
||||||
|
|
||||||
|
// 启动更新后的应用程序
|
||||||
|
ProcessStartInfo startInfo = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = newAppPath,
|
||||||
|
WorkingDirectory = targetPath,
|
||||||
|
UseShellExecute = false
|
||||||
|
};
|
||||||
|
|
||||||
|
Process newProcess = Process.Start(startInfo);
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 最终应用程序启动成功,PID: {newProcess?.Id}");
|
||||||
|
|
||||||
|
// 等待一小段时间确保最终应用程序启动
|
||||||
|
Thread.Sleep(2000);
|
||||||
|
|
||||||
|
// 结束当前更新进程
|
||||||
|
LogHelper.WriteLogToFile("AutoUpdate | 更新流程完成,结束更新进程");
|
||||||
|
|
||||||
|
// 强制结束当前更新进程
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("AutoUpdate | 强制结束更新进程");
|
||||||
|
Process.GetCurrentProcess().Kill();
|
||||||
|
// 如果Kill()没有立即生效,使用Environment.Exit强制退出
|
||||||
|
Thread.Sleep(100);
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 结束当前更新进程失败: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 启动更新后的应用程序失败: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
|
||||||
|
if (!isSilence)
|
||||||
|
{
|
||||||
|
MessageBox.Show($"更新完成,但启动应用程序失败:{ex.Message}\n请手动启动应用程序。", "启动失败", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 更新后的应用程序文件不存在: {newAppPath}", LogHelper.LogType.Error);
|
||||||
|
|
||||||
|
if (!isSilence)
|
||||||
|
{
|
||||||
|
MessageBox.Show($"更新完成,但未找到应用程序文件:{newAppPath}\n请检查更新是否成功。", "文件缺失", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 执行更新操作时出错: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
|
||||||
|
if (!isSilence)
|
||||||
|
{
|
||||||
|
MessageBox.Show($"更新失败:{ex.Message}", "更新失败", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 异步复制目录的辅助方法(带重试机制)
|
||||||
|
private static async Task<bool> CopyDirectoryWithRetryAsync(string sourceDir, string destinationDir)
|
||||||
|
{
|
||||||
|
var dir = new DirectoryInfo(sourceDir);
|
||||||
|
DirectoryInfo[] dirs = dir.GetDirectories();
|
||||||
|
bool allFilesCopied = true;
|
||||||
|
|
||||||
|
// 如果目标目录不存在,则创建它
|
||||||
|
if (!Directory.Exists(destinationDir))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(destinationDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 复制文件
|
||||||
|
foreach (FileInfo file in dir.GetFiles())
|
||||||
|
{
|
||||||
|
string targetFilePath = Path.Combine(destinationDir, file.Name);
|
||||||
|
bool fileCopied = false;
|
||||||
|
|
||||||
|
// 重试机制,最多重试3次
|
||||||
|
for (int retry = 0; retry < 3; retry++)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 如果目标文件存在,先尝试删除
|
||||||
|
if (File.Exists(targetFilePath))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.Delete(targetFilePath);
|
||||||
|
}
|
||||||
|
catch (IOException)
|
||||||
|
{
|
||||||
|
// 文件可能正在使用,等待一下再重试
|
||||||
|
if (retry < 2)
|
||||||
|
{
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Run(() => file.CopyTo(targetFilePath));
|
||||||
|
fileCopied = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 复制文件失败 (重试 {retry + 1}/3) {file.FullName} -> {targetFilePath}: {ex.Message}", LogHelper.LogType.Warning);
|
||||||
|
|
||||||
|
if (retry < 2)
|
||||||
|
{
|
||||||
|
Thread.Sleep(1000); // 等待1秒后重试
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fileCopied)
|
||||||
|
{
|
||||||
|
allFilesCopied = false;
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 文件复制最终失败: {file.FullName}", LogHelper.LogType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 递归复制子目录
|
||||||
|
foreach (DirectoryInfo subDir in dirs)
|
||||||
|
{
|
||||||
|
string newDestinationDir = Path.Combine(destinationDir, subDir.Name);
|
||||||
|
bool subDirCopied = await CopyDirectoryWithRetryAsync(subDir.FullName, newDestinationDir);
|
||||||
|
if (!subDirCopied)
|
||||||
|
{
|
||||||
|
allFilesCopied = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return allFilesCopied;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 异步复制目录的辅助方法(原版本,保留兼容性)
|
||||||
|
private static async Task CopyDirectoryAsync(string sourceDir, string destinationDir)
|
||||||
|
{
|
||||||
|
var dir = new DirectoryInfo(sourceDir);
|
||||||
|
DirectoryInfo[] dirs = dir.GetDirectories();
|
||||||
|
|
||||||
|
// 如果目标目录不存在,则创建它
|
||||||
|
if (!Directory.Exists(destinationDir))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(destinationDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 复制文件
|
||||||
|
foreach (FileInfo file in dir.GetFiles())
|
||||||
|
{
|
||||||
|
string targetFilePath = Path.Combine(destinationDir, file.Name);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 如果目标文件存在且正在使用,先删除
|
||||||
|
if (File.Exists(targetFilePath))
|
||||||
|
{
|
||||||
|
File.Delete(targetFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Run(() => file.CopyTo(targetFilePath));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"AutoUpdate | 复制文件失败 {file.FullName} -> {targetFilePath}: {ex.Message}", LogHelper.LogType.Warning);
|
||||||
|
// 继续复制其他文件,不中断整个过程
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 递归复制子目录
|
||||||
|
foreach (DirectoryInfo subDir in dirs)
|
||||||
|
{
|
||||||
|
string newDestinationDir = Path.Combine(destinationDir, subDir.Name);
|
||||||
|
await CopyDirectoryAsync(subDir.FullName, newDestinationDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 获取远程内容的通用方法
|
// 获取远程内容的通用方法
|
||||||
public static async Task<string> GetRemoteContent(string fileUrl)
|
public static async Task<string> GetRemoteContent(string fileUrl)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ using System.Windows;
|
|||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCompany("CJK_mkp")]
|
[assembly: AssemblyCompany("CJK_mkp")]
|
||||||
[assembly: AssemblyProduct("InkCanvasForClass")]
|
[assembly: AssemblyProduct("InkCanvasForClass")]
|
||||||
[assembly: AssemblyCopyright("© Copyright HARKOTEK Studio 2024-now")]
|
[assembly: AssemblyCopyright("Copyright © HARKOTEK Studio 2024")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
@@ -49,5 +49,5 @@ using System.Windows;
|
|||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("1.7.8.0")]
|
[assembly: AssemblyVersion("1.7.8.1")]
|
||||||
[assembly: AssemblyFileVersion("1.7.8.0")]
|
[assembly: AssemblyFileVersion("1.7.8.1")]
|
||||||
|
|||||||
Reference in New Issue
Block a user