diff --git a/VHDManager.cs b/VHDManager.cs
index 6c916f7..8d3d3e3 100644
--- a/VHDManager.cs
+++ b/VHDManager.cs
@@ -574,12 +574,20 @@ exit";
// 第二步:为第一个分区分配盘符
StatusChanged?.Invoke("步骤2: 为第一个分区分配盘符M...");
- // 容错检查:如果M盘已经存在,可能是系统自动分配的
+ // 容错检查:如果M盘已经存在,先删除再重新分配
if (Directory.Exists(TARGET_DRIVE))
{
- StatusChanged?.Invoke("检测到M盘已自动分配,跳过手动分配步骤");
- StatusChanged?.Invoke("VHD挂载和盘符分配完成");
- return true;
+ StatusChanged?.Invoke("检测到M盘已存在,正在删除原有盘符...");
+ bool removed = await RemoveExistingDriveLetter(vhdPath);
+ if (!removed)
+ {
+ StatusChanged?.Invoke("删除原有盘符失败,但继续尝试重新分配");
+ }
+ else
+ {
+ StatusChanged?.Invoke("原有盘符删除成功");
+ }
+ await Task.Delay(2000); // 等待系统更新
}
bool driveAssigned = await AssignDriveLetterToFirstPartition(vhdPath);
@@ -806,6 +814,89 @@ exit";
}
}
+ ///
+ /// 删除VHD第一个分区的现有盘符
+ ///
+ private async Task RemoveExistingDriveLetter(string vhdPath)
+ {
+ try
+ {
+ StatusChanged?.Invoke("正在删除VHD第一个分区的现有盘符...");
+
+ // 使用diskpart删除第一个分区的盘符
+ var removeScript = $@"select vdisk file=""{vhdPath}""
+list partition
+select partition 1
+remove letter=M
+exit";
+
+ var tempScript = Path.GetTempFileName();
+ await File.WriteAllTextAsync(tempScript, removeScript);
+
+ 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);
+
+ // 验证M盘是否已被删除
+ bool driveRemoved = !Directory.Exists(TARGET_DRIVE);
+ if (driveRemoved)
+ {
+ StatusChanged?.Invoke("盘符M删除成功");
+ }
+ else
+ {
+ StatusChanged?.Invoke("盘符M可能仍然存在,但继续处理");
+ }
+
+ return driveRemoved;
+ }
+ catch (Exception ex)
+ {
+ StatusChanged?.Invoke($"删除盘符异常: {ex.Message}");
+ Debug.WriteLine($"RemoveExistingDriveLetter异常: {ex}");
+ return false;
+ }
+ }
+
///
/// 为VHD的第一个分区分配盘符M
///
@@ -813,14 +904,6 @@ exit";
{
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
@@ -901,14 +984,8 @@ exit";
{
try
{
- // 容错机制:检查M盘是否已经存在
- if (Directory.Exists(TARGET_DRIVE))
- {
- StatusChanged?.Invoke("备用方法检测到M盘已存在,跳过盘符分配");
- Debug.WriteLine("备用方法:M盘已存在,无需重复分配");
- return true;
- }
-
+ StatusChanged?.Invoke("尝试备用盘符分配方法...");
+
// 尝试为最后挂载的磁盘分配盘符
var assignScript = @"list disk
select disk 1
diff --git a/VHD_Mount_Fix_Guide.md b/VHD_Mount_Fix_Guide.md
new file mode 100644
index 0000000..8d54f07
--- /dev/null
+++ b/VHD_Mount_Fix_Guide.md
@@ -0,0 +1,121 @@
+# VHD挂载修复测试指南
+
+## 修复内容
+
+本次修复解决了以下VHD挂载相关问题:
+
+1. **VHD解除挂载后程序卡住问题**
+ - 重写了`MountVHD`方法,采用两步式挂载流程
+ - 先挂载VHD文件,再为第一个分区分配盘符M
+ - 添加了完善的错误处理和超时机制
+
+2. **VHD挂载盘符处理兼容性问题**
+ - 新增`AssignDriveLetterToFirstPartition()`方法,专门处理分区盘符分配
+ - 新增`AssignDriveLetterDirect()`备用方法,提供兼容性支持
+ - 改进了diskpart脚本的执行和错误处理
+
+3. **智能盘符重新分配机制**
+ - 新增`RemoveExistingDriveLetter()`方法,用于删除已有盘符
+ - 当检测到M盘已存在时,先删除原有盘符,再重新分配
+ - 确保盘符分配的一致性和可靠性,避免冲突
+
+## 测试步骤
+
+### 准备工作
+1. 确保有管理员权限(VHD挂载需要管理员权限)
+2. 准备测试用的VHD文件
+3. 确保M盘符当前未被占用
+
+### 测试1:本地VHD挂载测试
+1. 将VHD文件放在本地目录
+2. 运行程序,选择本地VHD文件
+3. 观察挂载过程的状态输出
+4. 验证M盘是否成功挂载并可访问
+
+### 测试2:USB VHD替换测试
+1. 准备包含VHD文件的USB设备
+2. 插入USB设备
+3. 运行程序,让其自动检测并替换本地VHD
+4. 验证替换和挂载过程是否正常
+
+### 测试3:盘符冲突处理测试
+1. 手动创建一个M盘(可以是网络驱动器或其他)
+2. 运行程序挂载VHD
+3. 验证程序是否正确删除原有M盘并重新分配
+
+### 测试4:多分区VHD兼容性测试
+1. 使用包含多个分区的VHD文件
+2. 验证程序是否正确为第一个分区分配M盘符
+3. 检查其他分区是否不受影响
+
+## 预期输出示例
+
+### 正常挂载流程
+```
+开始挂载VHD: C:\path\to\file.vhd
+步骤1: 挂载VHD文件...
+VHD挂载成功,等待系统识别分区...
+步骤2: 为第一个分区分配盘符M...
+正在为第一个分区分配盘符M...
+盘符M分配成功
+VHD挂载和盘符分配完成
+```
+
+### 盘符冲突处理流程
+```
+开始挂载VHD: C:\path\to\file.vhd
+步骤1: 挂载VHD文件...
+VHD挂载成功,等待系统识别分区...
+步骤2: 为第一个分区分配盘符M...
+检测到M盘已存在,正在删除原有盘符...
+正在删除VHD第一个分区的现有盘符...
+盘符M删除成功
+原有盘符删除成功
+正在为第一个分区分配盘符M...
+盘符M分配成功
+VHD挂载和盘符分配完成
+```
+
+### 备用方法触发
+```
+分配盘符失败,尝试备用方法...
+尝试备用盘符分配方法...
+备用方法:盘符M分配成功
+VHD挂载和盘符分配完成
+```
+
+## 故障排除
+
+### 常见问题
+1. **权限不足**:确保以管理员身份运行程序
+2. **VHD文件损坏**:检查VHD文件是否完整
+3. **盘符冲突**:程序会自动处理M盘冲突,删除原有盘符后重新分配
+4. **系统资源不足**:确保有足够的内存和磁盘空间
+
+### 调试信息
+程序会在Debug输出中显示详细的操作信息,包括:
+- diskpart命令的执行结果
+- 盘符分配的详细过程
+- 错误信息和异常堆栈
+
+## 注意事项
+
+1. **管理员权限**:VHD挂载操作需要管理员权限
+2. **盘符占用**:程序会自动处理M盘冲突,无需手动干预
+3. **系统兼容性**:支持Windows 10/11系统
+4. **VHD格式**:支持标准的VHD和VHDX格式文件
+5. **安全性**:程序会在操作完成后自动清理临时文件
+
+## 技术细节
+
+### 盘符重新分配流程
+1. 检测M盘是否已存在
+2. 如果存在,使用diskpart删除原有盘符
+3. 等待系统更新(2秒延迟)
+4. 重新为VHD第一个分区分配M盘符
+5. 验证分配结果
+
+### 容错机制
+- 删除盘符失败时,程序仍会尝试重新分配
+- 主要分配方法失败时,自动尝试备用方法
+- 所有操作都有超时保护,避免程序卡死
\ No newline at end of file