c++ - 以编程方式安装 Microsoft 虚拟硬盘驱动器 (VHD)

标签 c++ winapi mount vhd

我尝试使用 Windows 7 API 函数挂载虚拟硬盘 (.VHD),但找不到相关函数,是否存在?

我正在使用 Visual Studio 2010 进行 C++ 编程,以获取信息。

提前致谢;)

最佳答案

这是一个老问题,但仍然没有答案,所以我会提供一个答案,以防有人像我一样偶然发现它。

附加 VHD

有关 MSDN [VHD 引用] 上的完整引用:http://msdn.microsoft.com/en-us/library/windows/desktop/dd323700(v=vs.85).aspx

OPEN_VIRTUAL_DISK_PARAMETERS openParameters;
openParameters.Version = OPEN_VIRTUAL_DISK_VERSION_1;
openParameters.Version1.RWDepth = OPEN_VIRTUAL_DISK_RW_DEPTH_DEFAULT;

VIRTUAL_STORAGE_TYPE storageType;
storageType.DeviceID = VIRTUAL_STORAGE_TYPE_DEVICE_VHD;
storageType.VendorId = VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT;

ATTACH_VIRTUAL_DISK_PARAMETERS attachParameters;
attachParameters.Version = ATTACH_VIRTUAL_DISK_VERSION_1;

HANDLE vhdHandle;

if (OpenVirtualDisk(&openStorageType, "{VHD PATH GOES HERE}", 
        VIRTUAL_DISK_ACCESS_ALL, OPEN_VIRTUAL_DISK_FLAG_NONE, 
        &openParameters, &vhdHandle) != ERROR_SUCCESS) {
    // If return value of OpenVirtualDisk isn't ERROR_SUCCESS, there was a problem opening the VHD
}

// Warning: AttachVirtualDisk requires elevation
if (AttachVirtualDisk(vhdHandle, 0, ATTACH_VIRTUAL_DISK_FLAG_PERMANENT_LIFETIME,
        0, &attachParameters, 0) != ERROR_SUCCESS) {
    // If return value of AttachVirtualDisk isn't ERROR_SUCCESS, there was a problem attach the disk
}

VHD 已成功附加,现在它将像任何其他物理磁盘一样显示,并且驱动器号将自动分配给 VHD 中包含的卷。如果您想选择用于安装它的驱动器号,请继续阅读。

分配驱动器号

首先,将 ATTACH_VIRTUAL_DISK_FLAG_NO_DRIVE_LETTER 标志添加到您的 AttachVirtualDisk 调用中,这样它就不会执行此自动字母分配操作。接下来,您必须找到 VHD 卷的卷路径 [其格式为:\\?\Volume{GUID}]:

wchar_t physicalDrive[MAX_PATH];
ULONG bufferSize = sizeof(physicalDrive);
GetVirtualDiskPhysicalPath(vhdHandle, &bufferSize, physicalDrive);

现在,您将在物理驱动器中获得附加 VHD 的物理路径,格式如下:\\.\PhysicalDrive#,其中 # 是您使用 FindFirstVolume/FindNextVolume 查找 VHD 卷所需的驱动器号。提取数字并将其转换为整数,然后您就可以编写下一段代码了:

char volumeName[MAX_PATH];
DWORD bytesReturned;
VOLUME_DISK_EXTENTS diskExtents;    
HANDLE hFVol = FindFirstVolume(volumeName, sizeof(volumeName)); 
bool hadTrailingBackslash = false;

do {
    // I had a problem where CreateFile complained about the trailing \ and
    // SetVolumeMountPoint desperately wanted the backslash there. I ended up 
    // doing this to get it working but I'm not a fan and I'd greatly 
    // appreciate it if someone has any further info on this matter
    int backslashPos = strlen(volumeName) - 1;
    if (hadTrailingBackslash = volumeName[backslashPos] == '\\') {
        volumeName[backslashPos] = 0;
    }

    HANDLE hVol = CreateFile(volumeName, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
    if (hVol == INVALID_HANDLE_VALUE) {
        return;
    }

    DeviceIoControl(hVol, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL,
        0, &diskExtents, sizeof(diskExtents), &bytesReturned, NULL);

    // If the volume were to span across multiple physical disks, you'd find 
    // more than one Extents here but we don't have to worry about that with VHD
    // Note that 'driveNumber' would be the integer you extracted out of 
    // 'physicalDrive' in the previous snippet
    if (diskExtents.Extents[0].DiskNumber == driveNumber) {
        if (hadTrailingBackslash) {
            volumeName[backslashPos] = '\\';
        }

        // Found volume that's on the VHD, let's mount it with a letter of our choosing.
        // Warning: SetVolumeMountPoint requires elevation
        SetVolumeMountPoint("H:\\", volumeName);
    } 
} while (FindNextVolume(hFVol, volumeName, sizeof(volumeName)));
FindVolumeClose(hFVol);

不要忘记这些包含内容并链接到该库:

#define WINVER _WIN32_WINNT_WIN7
#include <windows.h>
#include <winioctl.h>
#include <virtdisk.h>

#pragma comment(lib, "virtdisk.lib")

免责声明:这是我在 C# 代码库中所做的事情,由于这个问题,我将代码翻译为 C/C++,但尚未尝试实际编译它。如果您发现代码中有错误,请编辑它或让我知道,以便我可以做到这一点。

编辑:拼写错误、包含和库、忘记 FindVolumeClose、海拔警告

关于c++ - 以编程方式安装 Microsoft 虚拟硬盘驱动器 (VHD),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24396644/

相关文章:

linux - 您好,使用 NFS 挂载和共享服务器

c++ - 如何从原始数据加载 devIL 图像

c++ - c++0x 中用户定义文字的重载规则

c++ - -读取字符串字符时出错

c++ - 在离开模式下唤醒 Windows

linux - 手动移除 USB 后挂载目录仍显示数据

mongodb - 使用Docker的MongoDB分片群集具有持久性存储问题

c++ - 在 C++ 程序中使用 unicode

c - 删除文件结尾

c++ - FindFirstFile LPCSTR