From 358fb4ce14242864d2a2a6b923e8e7a22ae5df66 Mon Sep 17 00:00:00 2001 From: Lannamokia Date: Mon, 20 Oct 2025 03:35:23 +0800 Subject: [PATCH] =?UTF-8?q?feat(VHDManager):=20=E6=B7=BB=E5=8A=A0Win11?= =?UTF-8?q?=E5=85=BC=E5=AE=B9=E6=80=A7=E6=A3=80=E6=9F=A5=E5=92=8C=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=A4=84=E7=90=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除未使用的VHDFilesFound事件及相关代码 - 新增Win11兼容性诊断功能,检查操作系统版本和管理员权限 - 添加文件占用检测和属性修复功能 - 改进文件替换流程,增加错误处理和状态报告 - 添加详细的诊断日志记录 - 新增Win11故障排除文档 --- MainWindow.xaml.cs | 10 +-- VHDManager.cs | 189 +++++++++++++++++++++++++++++++++++++-- Win11_Troubleshooting.md | 92 +++++++++++++++++++ 3 files changed, 275 insertions(+), 16 deletions(-) create mode 100644 Win11_Troubleshooting.md diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs index c872085..f6023fe 100644 --- a/MainWindow.xaml.cs +++ b/MainWindow.xaml.cs @@ -19,7 +19,6 @@ namespace VHDMounter InitializeComponent(); vhdManager = new VHDManager(); vhdManager.StatusChanged += OnStatusChanged; - vhdManager.VHDFilesFound += OnVHDFilesFound; // 注册关机事件监听 SystemEvents.SessionEnding += OnSessionEnding; @@ -36,14 +35,7 @@ namespace VHDMounter }); } - private void OnVHDFilesFound(List vhdFiles) - { - Dispatcher.Invoke(() => - { - availableVHDs = vhdFiles; - ShowVHDSelector(vhdFiles); - }); - } + private async Task StartMainProcessWithDelay() { diff --git a/VHDManager.cs b/VHDManager.cs index f79d304..c8ccff7 100644 --- a/VHDManager.cs +++ b/VHDManager.cs @@ -19,7 +19,6 @@ namespace VHDMounter private readonly string[] PROCESS_KEYWORDS = { "sinmai", "chusanapp", "mu3" }; public event Action StatusChanged; - public event Action> VHDFilesFound; private static readonly HttpClient httpClient = new HttpClient(); private string configFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "vhdmonter_config.ini"); @@ -117,6 +116,9 @@ namespace VHDMounter if (usbVhdFiles.Count == 0 || localVhdFiles.Count == 0) return false; + // Win11兼容性诊断 + DiagnoseWin11Issues(); + bool anyReplaced = false; StatusChanged?.Invoke("正在替换本地VHD文件..."); @@ -138,22 +140,78 @@ namespace VHDMounter { try { + // Win11兼容性检查和准备 + StatusChanged?.Invoke($"检查Win11兼容性: {Path.GetFileName(localFile)}"); + var localFileInfo = new FileInfo(localFile); + var usbFileInfo = new FileInfo(usbFile); + + // 记录文件属性用于诊断 + Debug.WriteLine($"本地文件属性: {localFileInfo.Attributes}, 只读: {localFileInfo.IsReadOnly}"); + Debug.WriteLine($"USB文件属性: {usbFileInfo.Attributes}, 大小: {usbFileInfo.Length} bytes"); + Debug.WriteLine($"操作系统版本: {Environment.OSVersion}"); + + // 检查文件是否被占用 + if (IsFileInUse(localFile)) + { + StatusChanged?.Invoke($"文件被占用,无法删除: {Path.GetFileName(localFile)}"); + Debug.WriteLine($"文件被占用: {localFile}"); + continue; + } + + // Win11兼容性处理 + if (!PrepareFileForReplacement(localFile)) + { + StatusChanged?.Invoke($"无法准备文件进行替换: {Path.GetFileName(localFile)}"); + continue; + } + // 直接删除本地文件 StatusChanged?.Invoke($"正在删除本地文件: {Path.GetFileName(localFile)}"); if (File.Exists(localFile)) File.Delete(localFile); + // 等待文件系统完成删除操作 + int retryCount = 0; + while (File.Exists(localFile) && retryCount < 10) + { + await Task.Delay(100); + retryCount++; + } + + if (File.Exists(localFile)) + { + StatusChanged?.Invoke($"删除文件失败,文件仍然存在: {Path.GetFileName(localFile)}"); + continue; + } + // 复制USB文件到本地 StatusChanged?.Invoke($"正在用 {Path.GetFileName(usbFile)} 替换 {Path.GetFileName(localFile)}"); File.Copy(usbFile, localFile); + // 验证复制结果 + var newFileInfo = new FileInfo(localFile); + if (newFileInfo.Length != usbFileInfo.Length) + { + StatusChanged?.Invoke($"警告: 文件大小不匹配 - 原始: {usbFileInfo.Length}, 复制后: {newFileInfo.Length}"); + } + anyReplaced = true; StatusChanged?.Invoke($"替换完成: {Path.GetFileName(localFile)}"); } + catch (UnauthorizedAccessException ex) + { + StatusChanged?.Invoke($"权限不足,无法替换文件: {Path.GetFileName(localFile)} - {ex.Message}"); + Debug.WriteLine($"权限错误: {ex}"); + } + catch (IOException ex) + { + StatusChanged?.Invoke($"文件IO错误: {Path.GetFileName(localFile)} - {ex.Message}"); + Debug.WriteLine($"IO错误: {ex}"); + } catch (Exception ex) { - StatusChanged?.Invoke($"替换文件时出错: {ex.Message}"); - Debug.WriteLine($"替换文件时出错: {ex.Message}"); + StatusChanged?.Invoke($"替换文件时出错: {Path.GetFileName(localFile)} - {ex.Message}"); + Debug.WriteLine($"替换文件时出错: {ex}"); } } } @@ -173,6 +231,123 @@ namespace VHDMounter return string.Empty; } + // 检查文件是否被占用 + private bool IsFileInUse(string filePath) + { + try + { + using (FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) + { + return false; + } + } + catch (IOException) + { + return true; + } + catch (UnauthorizedAccessException) + { + return true; + } + } + + // Win11兼容性检查和修复 + private bool PrepareFileForReplacement(string filePath) + { + try + { + var fileInfo = new FileInfo(filePath); + + // 检查文件是否存在 + if (!fileInfo.Exists) + return true; + + // 移除只读属性 + if (fileInfo.IsReadOnly) + { + StatusChanged?.Invoke($"移除只读属性: {fileInfo.Name}"); + fileInfo.IsReadOnly = false; + } + + // 移除隐藏和系统属性(Win11可能设置这些属性) + if ((fileInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden) + { + StatusChanged?.Invoke($"移除隐藏属性: {fileInfo.Name}"); + fileInfo.Attributes &= ~FileAttributes.Hidden; + } + + if ((fileInfo.Attributes & FileAttributes.System) == FileAttributes.System) + { + StatusChanged?.Invoke($"移除系统属性: {fileInfo.Name}"); + fileInfo.Attributes &= ~FileAttributes.System; + } + + // 检查是否有写入权限 + try + { + using (var stream = File.OpenWrite(filePath)) + { + // 如果能打开写入流,说明有权限 + } + } + catch (UnauthorizedAccessException) + { + StatusChanged?.Invoke($"权限不足,无法写入文件: {fileInfo.Name}"); + return false; + } + + return true; + } + catch (Exception ex) + { + StatusChanged?.Invoke($"准备文件时出错: {ex.Message}"); + Debug.WriteLine($"PrepareFileForReplacement错误: {ex}"); + return false; + } + } + + // 检测Win11并提供诊断信息 + private void DiagnoseWin11Issues() + { + try + { + var osVersion = Environment.OSVersion; + var isWin11 = osVersion.Version.Major >= 10 && osVersion.Version.Build >= 22000; + + StatusChanged?.Invoke($"操作系统: {osVersion.VersionString}"); + Debug.WriteLine($"操作系统详细信息: {osVersion}"); + Debug.WriteLine($"是否为Win11: {isWin11}"); + + if (isWin11) + { + StatusChanged?.Invoke("检测到Windows 11,启用兼容性模式"); + + // 检查UAC状态 + try + { + var principal = new System.Security.Principal.WindowsPrincipal(System.Security.Principal.WindowsIdentity.GetCurrent()); + bool isAdmin = principal.IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator); + + StatusChanged?.Invoke($"管理员权限: {(isAdmin ? "是" : "否")}"); + Debug.WriteLine($"当前进程是否以管理员身份运行: {isAdmin}"); + + if (!isAdmin) + { + StatusChanged?.Invoke("建议:以管理员身份运行程序以避免权限问题"); + } + } + catch (Exception ex) + { + Debug.WriteLine($"检查管理员权限时出错: {ex}"); + } + } + } + catch (Exception ex) + { + Debug.WriteLine($"Win11诊断时出错: {ex}"); + } + } + // 读取配置文件 private Dictionary ReadConfig() { @@ -536,14 +711,14 @@ exit"; return await FindFolder("package"); } - public async Task StartBatchFile(string packagePath) + public Task StartBatchFile(string packagePath) { var startBatPath = Path.Combine(packagePath, "start.bat"); if (!File.Exists(startBatPath)) { StatusChanged?.Invoke("未找到start.bat文件"); - return false; + return Task.FromResult(false); } StatusChanged?.Invoke("正在启动start.bat..."); @@ -562,12 +737,12 @@ exit"; }; process.Start(); - return true; + return Task.FromResult(true); } catch (Exception ex) { StatusChanged?.Invoke($"启动失败: {ex.Message}"); - return false; + return Task.FromResult(false); } } diff --git a/Win11_Troubleshooting.md b/Win11_Troubleshooting.md new file mode 100644 index 0000000..4e8eade --- /dev/null +++ b/Win11_Troubleshooting.md @@ -0,0 +1,92 @@ +# Windows 11 VHD替换故障排除指南 + +## 问题描述 +在Windows 11系统上,VHD文件替换可能会失败,这通常是由于Win11增强的安全策略和文件保护机制导致的。 + +## 常见错误原因 + +### 1. 权限问题 +- **症状**: 提示"权限不足,无法替换文件" +- **原因**: Win11的UAC(用户账户控制)更加严格 +- **解决方案**: + - 右键点击程序,选择"以管理员身份运行" + - 或者在程序属性中设置"始终以管理员身份运行" + +### 2. 文件属性问题 +- **症状**: 文件无法删除或替换 +- **原因**: Win11可能自动设置VHD文件为只读、隐藏或系统文件 +- **解决方案**: 程序现在会自动检测并移除这些属性 + +### 3. 文件被占用 +- **症状**: 提示"文件被占用,无法删除" +- **原因**: VHD文件可能被Windows资源管理器或其他程序占用 +- **解决方案**: + - 关闭所有文件资源管理器窗口 + - 确保没有其他程序正在访问VHD文件 + - 重启计算机后再尝试 + +### 4. Windows Defender实时保护 +- **症状**: 文件操作被阻止或延迟 +- **原因**: Windows Defender可能将VHD文件操作视为可疑行为 +- **解决方案**: + - 临时禁用实时保护 + - 或将VHD文件夹添加到排除列表 + +## 程序改进功能 + +### 新增的Win11兼容性检查 +程序现在包含以下改进: + +1. **自动检测Win11**: 程序会自动识别是否运行在Windows 11上 +2. **权限检查**: 检查程序是否以管理员身份运行 +3. **文件属性修复**: 自动移除只读、隐藏、系统等属性 +4. **文件占用检测**: 检查文件是否被其他程序占用 +5. **详细错误报告**: 提供更详细的错误信息和诊断数据 + +### 诊断信息 +程序会在状态栏显示以下信息: +- 操作系统版本 +- 管理员权限状态 +- 文件属性详情 +- 具体的错误原因 + +## 手动排除步骤 + +### 步骤1: 检查权限 +1. 右键点击VHDMounter.exe +2. 选择"属性" → "兼容性" +3. 勾选"以管理员身份运行此程序" +4. 点击"确定" + +### 步骤2: 检查文件属性 +1. 右键点击VHD文件 +2. 选择"属性" +3. 取消勾选"只读" +4. 在"高级"中取消勾选"隐藏"和"系统" + +### 步骤3: 检查Windows Defender +1. 打开Windows安全中心 +2. 转到"病毒和威胁防护" +3. 在"病毒和威胁防护设置"中点击"管理设置" +4. 临时关闭"实时保护"或添加排除项 + +### 步骤4: 检查磁盘空间 +确保目标磁盘有足够的空间存储VHD文件 + +### 步骤5: 重启服务 +如果问题持续,尝试重启以下服务: +- Windows资源管理器 (explorer.exe) +- 虚拟磁盘服务 (vds) + +## 联系支持 +如果以上步骤都无法解决问题,请提供以下信息: +1. 程序显示的具体错误消息 +2. Windows 11版本号 +3. VHD文件大小和位置 +4. 是否以管理员身份运行程序 + +## 预防措施 +1. 始终以管理员身份运行程序 +2. 定期检查VHD文件的属性设置 +3. 保持Windows 11系统更新 +4. 避免在系统保护的文件夹中存储VHD文件 \ No newline at end of file