65.9K
CodeProject 正在变化。 阅读更多。
Home

Windows 虚拟硬盘

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.96/5 (18投票s)

2017 年 1 月 2 日

GPL3

3分钟阅读

viewsIcon

25755

downloadIcon

1382

一个可以方便地从 Windows 系统镜像备份中挂载/卸载 VHD 文件的工具

引言

Windows 7 附带一个系统镜像备份实用程序,可以通过控制面板(备份和还原/创建系统镜像)或命令行(sdclt.exe /BLBBACKUPWIZARD)启动。此工具在 Windows 8 和 10 中也可用,允许您创建完整硬盘的备份。这些备份稍后可用于恢复崩溃的系统。

每个驱动器都存储在一个扩展名为 ".vhd"(虚拟硬盘)的文件中,好消息是您可以使用磁盘管理工具挂载这些文件,并使用 Windows 资源管理器单独访问所有文件。坏消息是,使用 Windows 工具挂载和卸载 VHD 文件非常繁琐。

背景

在外部硬盘驱动器上创建系统映像备份时,VHD 文件存储在这样的文件夹中:'WindowsImageBackup\计算机名\Backup yyyy-MM-dd hhmmss'。此文件夹还包含一个名为 'BackupSpecs.xml' 的文件,其中包含有关已保存驱动器的信息,例如,原始驱动器盘符和该驱动器的 VHD 文件名。

多年来,我一直使用 Windows 磁盘管理工具(控制面板\管理工具\计算机管理\磁盘管理)将 VHD 文件附加到系统(磁盘管理\操作\附加 VHD),但是

  1. 直到你可以选择一个VHD文件,需要大量的鼠标点击
  2. 一旦你到达那里,你不知道哪个原始驱动器存储在一个文件中

前几天我了解到 'DiskPart.exe'(Windows 自带)也可以完成这项工作。有一篇很好的文章介绍如何直接从 Windows 资源管理器附加/分离 VHD 文件 这里。虽然这有助于节省大量的鼠标点击,但您仍然必须猜测哪个驱动器存储在特定文件中。并且一旦附加了一个文件,在分离时你需要记住它的路径。

因此,我开始编写这个小型实用程序来帮助我。启动时,它会在每个可用硬盘驱动器的根目录下查找 'WindowsImageBackup' 文件夹。每个映射到类似 'C:\' 或 'D:\' 的 VHD 文件都会添加到 UI 上显示的列表中。您还可以看到计算机的名称、原始驱动器盘符以及备份的日期和大小。

要挂载驱动器,只需单击它旁边的复选框。如果挂载成功,则会在右侧显示一个新的驱动器盘符。要卸载驱动器,只需再次单击复选框即可。

一些代码细节

这个WPF应用程序中没有什么特别复杂的,这里有一点数据绑定,那里有一点LINQ,所以让我们来看看代码的核心,即MountVHD方法

bool MountVHD(string fileName, bool mode)
{
    if (!File.Exists(fileName))
        return false;

    Remember(fileName);
    var script = Path.GetTempPath() + "diskpart.txt";
    File.WriteAllText(script, string.Format
        ("select vdisk file=\"{0}\"\r\n{1} vdisk", 
        fileName, mode ? "attach" : "detach"));

    var process = new Process();
    process.StartInfo.FileName = "diskpart.exe";
    process.StartInfo.Arguments = string.Format("/s \"{0}\"", script);
    process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
    process.Start();

    var result = false;
    while (true)
    {
        process.WaitForExit(7000);
        if (process.HasExited)
        {
            if (process.ExitCode == 0)
                result = true;
            else
                MessageBox.Show(string.Format("Exit code = {0}", 
                          (uint)process.ExitCode), "MountVHD Error");
            break;
        }

        var answer = MessageBox.Show("Mounting the VHD takes long! Wait another 7 seconds?", 
                     "MountVHD", MessageBoxButton.YesNo, MessageBoxImage.Question);
        if (answer == MessageBoxResult.No)
            break;
    }

    File.Delete(script);
    return result;
}

参数 'fileName' 是 VHD 文件的名称,参数 'mode' 用于附加或分离文件。

在检查文件是否存在并保存一些设置(以了解已附加的文件)后,将创建一个临时脚本文件。此文件包含 DiskPart 可执行文件的命令,该可执行文件接下来使用 Process 类启动。

以下while循环只是等待进程完成。如果未在 7 秒内发生,用户可以选择再等待 7 秒或取消循环。最后,脚本文件被删除。

就是这样!

希望你喜欢它,并发现该工具有用。如果您想查看更多代码,请查看我在 github 上的存储库。

历史

  • 2017-01-04:添加了清单文件和一些 try-catch 块
  • 2017-01-03:现在使用 TreeView
  • 2017-01-02:首次上传
© . All rights reserved.