diff --git a/VHDManager.cs b/VHDManager.cs
index c8ccff7..6c916f7 100644
--- a/VHDManager.cs
+++ b/VHDManager.cs
@@ -516,13 +516,14 @@ namespace VHDMounter
await UnmountDrive();
await UnmountVHD();
- var diskpartScript = $@"select vdisk file=""{vhdPath}""
+ // 第一步:仅挂载VHD,不分配盘符
+ StatusChanged?.Invoke("步骤1: 挂载VHD文件...");
+ var attachScript = $@"select vdisk file=""{vhdPath}""
attach vdisk
-assign letter=M
exit";
var tempScript = Path.GetTempFileName();
- await File.WriteAllTextAsync(tempScript, diskpartScript);
+ await File.WriteAllTextAsync(tempScript, attachScript);
var process = new Process
{
@@ -547,39 +548,64 @@ exit";
if (completed == timeoutTask)
{
try { process.Kill(); } catch { }
- StatusChanged?.Invoke("挂载超时(超过60秒),已中止diskpart进程");
- File.Delete(tempScript);
+ StatusChanged?.Invoke("VHD挂载超时(超过60秒),已中止diskpart进程");
+ if (File.Exists(tempScript))
+ File.Delete(tempScript);
return false;
}
- string output = await process.StandardOutput.ReadToEndAsync();
- string error = await process.StandardError.ReadToEndAsync();
+ string attachOutput = await process.StandardOutput.ReadToEndAsync();
+ string attachError = await process.StandardError.ReadToEndAsync();
- File.Delete(tempScript);
+ if (File.Exists(tempScript))
+ File.Delete(tempScript);
- // 等待系统完成卷挂载
- await Task.Delay(2000);
-
- bool mounted = Directory.Exists(TARGET_DRIVE);
- if (!mounted)
+ if (process.ExitCode != 0)
{
- if (!string.IsNullOrWhiteSpace(error))
- {
- StatusChanged?.Invoke($"挂载失败:{error.Trim()}");
- }
- else
- {
- // 提供有限的DiskPart输出以辅助定位问题
- var trimmedOutput = output?.Length > 400 ? output.Substring(output.Length - 400) : output;
- StatusChanged?.Invoke($"挂载失败:未检测到M盘。DiskPart输出片段:{trimmedOutput}");
- }
+ StatusChanged?.Invoke($"VHD挂载失败: {attachError.Trim()}");
+ Debug.WriteLine($"VHD挂载输出: {attachOutput}");
+ Debug.WriteLine($"VHD挂载错误: {attachError}");
+ return false;
}
- return mounted;
+ StatusChanged?.Invoke("VHD挂载成功,等待系统识别分区...");
+ await Task.Delay(3000); // 等待系统识别分区
+
+ // 第二步:为第一个分区分配盘符
+ StatusChanged?.Invoke("步骤2: 为第一个分区分配盘符M...");
+
+ // 容错检查:如果M盘已经存在,可能是系统自动分配的
+ if (Directory.Exists(TARGET_DRIVE))
+ {
+ StatusChanged?.Invoke("检测到M盘已自动分配,跳过手动分配步骤");
+ StatusChanged?.Invoke("VHD挂载和盘符分配完成");
+ return true;
+ }
+
+ bool driveAssigned = await AssignDriveLetterToFirstPartition(vhdPath);
+
+ if (!driveAssigned)
+ {
+ StatusChanged?.Invoke("分配盘符失败,尝试备用方法...");
+ // 备用方法:直接尝试分配盘符
+ driveAssigned = await AssignDriveLetterDirect();
+ }
+
+ if (driveAssigned)
+ {
+ StatusChanged?.Invoke("VHD挂载和盘符分配完成");
+ return true;
+ }
+ else
+ {
+ StatusChanged?.Invoke("盘符分配失败,但VHD已挂载");
+ return false;
+ }
}
catch (Exception ex)
{
StatusChanged?.Invoke($"挂载失败: {ex.Message}");
+ Debug.WriteLine($"MountVHD异常: {ex}");
return false;
}
}
@@ -780,6 +806,183 @@ exit";
}
}
+ ///
+ /// 为VHD的第一个分区分配盘符M
+ ///
+ private async Task AssignDriveLetterToFirstPartition(string vhdPath)
+ {
+ try
+ {
+ // 容错机制:检查M盘是否已经存在
+ if (Directory.Exists(TARGET_DRIVE))
+ {
+ StatusChanged?.Invoke("检测到M盘已存在,跳过盘符分配");
+ Debug.WriteLine("M盘已存在,无需重复分配");
+ return true;
+ }
+
+ // 使用diskpart列出VHD的分区并为第一个分区分配盘符
+ var listScript = $@"select vdisk file=""{vhdPath}""
+list partition
+select partition 1
+assign letter=M
+exit";
+
+ var tempScript = Path.GetTempFileName();
+ await File.WriteAllTextAsync(tempScript, listScript);
+
+ var process = new Process
+ {
+ StartInfo = new ProcessStartInfo
+ {
+ FileName = "diskpart",
+ Arguments = $"/s \"{tempScript}\"",
+ UseShellExecute = false,
+ CreateNoWindow = true,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true
+ }
+ };
+
+ process.Start();
+
+ var waitTask = process.WaitForExitAsync();
+ var timeoutTask = Task.Delay(30000);
+ var completed = await Task.WhenAny(waitTask, timeoutTask);
+
+ if (completed == timeoutTask)
+ {
+ try { process.Kill(); } catch { }
+ StatusChanged?.Invoke("分配盘符超时");
+ if (File.Exists(tempScript))
+ File.Delete(tempScript);
+ return false;
+ }
+
+ string output = await process.StandardOutput.ReadToEndAsync();
+ string error = await process.StandardError.ReadToEndAsync();
+
+ if (File.Exists(tempScript))
+ File.Delete(tempScript);
+
+ Debug.WriteLine($"分区盘符分配输出: {output}");
+ if (!string.IsNullOrWhiteSpace(error))
+ {
+ Debug.WriteLine($"分区盘符分配错误: {error}");
+ }
+
+ // 等待盘符分配完成
+ await Task.Delay(2000);
+
+ bool driveExists = Directory.Exists(TARGET_DRIVE);
+ if (driveExists)
+ {
+ StatusChanged?.Invoke("盘符M分配成功");
+ }
+ else
+ {
+ StatusChanged?.Invoke("盘符M分配失败,M盘不存在");
+ }
+
+ return driveExists;
+ }
+ catch (Exception ex)
+ {
+ StatusChanged?.Invoke($"分配盘符异常: {ex.Message}");
+ Debug.WriteLine($"AssignDriveLetterToFirstPartition异常: {ex}");
+ return false;
+ }
+ }
+
+ ///
+ /// 备用方法:直接尝试分配盘符(适用于单分区VHD)
+ ///
+ private async Task AssignDriveLetterDirect()
+ {
+ try
+ {
+ // 容错机制:检查M盘是否已经存在
+ if (Directory.Exists(TARGET_DRIVE))
+ {
+ StatusChanged?.Invoke("备用方法检测到M盘已存在,跳过盘符分配");
+ Debug.WriteLine("备用方法:M盘已存在,无需重复分配");
+ return true;
+ }
+
+ // 尝试为最后挂载的磁盘分配盘符
+ var assignScript = @"list disk
+select disk 1
+list partition
+select partition 1
+assign letter=M
+exit";
+
+ var tempScript = Path.GetTempFileName();
+ await File.WriteAllTextAsync(tempScript, assignScript);
+
+ var process = new Process
+ {
+ StartInfo = new ProcessStartInfo
+ {
+ FileName = "diskpart",
+ Arguments = $"/s \"{tempScript}\"",
+ UseShellExecute = false,
+ CreateNoWindow = true,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true
+ }
+ };
+
+ process.Start();
+
+ var waitTask = process.WaitForExitAsync();
+ var timeoutTask = Task.Delay(30000);
+ var completed = await Task.WhenAny(waitTask, timeoutTask);
+
+ if (completed == timeoutTask)
+ {
+ try { process.Kill(); } catch { }
+ StatusChanged?.Invoke("备用盘符分配超时");
+ if (File.Exists(tempScript))
+ File.Delete(tempScript);
+ return false;
+ }
+
+ string output = await process.StandardOutput.ReadToEndAsync();
+ string error = await process.StandardError.ReadToEndAsync();
+
+ if (File.Exists(tempScript))
+ File.Delete(tempScript);
+
+ Debug.WriteLine($"备用盘符分配输出: {output}");
+ if (!string.IsNullOrWhiteSpace(error))
+ {
+ Debug.WriteLine($"备用盘符分配错误: {error}");
+ }
+
+ // 等待盘符分配完成
+ await Task.Delay(2000);
+
+ bool driveExists = Directory.Exists(TARGET_DRIVE);
+ if (driveExists)
+ {
+ StatusChanged?.Invoke("备用方法盘符M分配成功");
+ }
+ else
+ {
+ StatusChanged?.Invoke("备用方法盘符M分配也失败");
+ }
+
+ return driveExists;
+ }
+ catch (Exception ex)
+ {
+ StatusChanged?.Invoke($"备用盘符分配异常: {ex.Message}");
+ Debug.WriteLine($"AssignDriveLetterDirect异常: {ex}");
+ return false;
+ }
+ }
+
public async Task UnmountVHD()
{
StatusChanged?.Invoke("正在解除VHD挂载...");
diff --git a/Win11_Troubleshooting.md b/Win11_Troubleshooting.md
deleted file mode 100644
index 4e8eade..0000000
--- a/Win11_Troubleshooting.md
+++ /dev/null
@@ -1,92 +0,0 @@
-# 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