如何获取物理驱动器的卷 ID?

Posted

技术标签:

【中文标题】如何获取物理驱动器的卷 ID?【英文标题】:How to get the physical drive's volume id? 【发布时间】:2016-10-02 23:31:36 【问题描述】:

问题

我正在尝试从物理驱动器获取卷 ID。

我的代码

// define disk handle
HANDLE VDHANDLE;

// set "open disk" parameters
OPEN_VIRTUAL_DISK_PARAMETERS VHD_OPEN_PARAM;
VHD_OPEN_PARAM.Version = OPEN_VIRTUAL_DISK_VERSION_1;
VHD_OPEN_PARAM.Version1.RWDepth = OPEN_VIRTUAL_DISK_RW_DEPTH_DEFAULT;

// set storage type
VIRTUAL_STORAGE_TYPE VHD_STORAGE;
VHD_STORAGE.DeviceId = VIRTUAL_STORAGE_TYPE_DEVICE_VHD;
VHD_STORAGE.VendorId = VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT;

// set "attach disk" parameters
ATTACH_VIRTUAL_DISK_PARAMETERS VHD_ATTACH_PARAM;
VHD_ATTACH_PARAM.Version = ATTACH_VIRTUAL_DISK_VERSION_1;

// open disk
if ( OpenVirtualDisk( &VHD_STORAGE, L"F:\\MyStorageBunker.vhd",
                      VIRTUAL_DISK_ACCESS_ALL, OPEN_VIRTUAL_DISK_FLAG_NONE,
                      &VHD_OPEN_PARAM, &VDHANDLE ) != ERROR_SUCCESS )

    return ERR_MOUNT_SCRIPTCREATE;


// attach drive
if ( AttachVirtualDisk( VDHANDLE, 0, ATTACH_VIRTUAL_DISK_FLAG_PERMANENT_LIFETIME,
                        0, &VHD_ATTACH_PARAM, 0 ) != ERROR_SUCCESS )

    return ERR_MOUNT_SCRIPTEXECUTE;


// Get attached drive & info
wchar_t DriveInfo[ MAX_PATH ];
ULONG bufferSize = sizeof( DriveInfo );
GetVirtualDiskPhysicalPath( VDHANDLE, &bufferSize, DriveInfo );
// DriveInfo raw output = \PHYSICALDISKX
// X = volume id

我尝试了什么

std::wstringstream tmp;
int value;
char c;
std::wstringstream  ss( DriveInfo );
ss >> tmp >> c >> value;

问题

没有运算符“>>”匹配这些操作数

问题

    如何从wchar_t DriveInfo 中提取卷ID? 除了GetVirtualDiskPhysicalPath,还有什么方法可以获取volume id吗?

【问题讨论】:

通常,物理驱动器对象没有卷 ID - 只有该驱动器上的各个分区有。我认为安装的.vhd 通常也是如此。 (但我不确定您安装 ISO 的情况。) 【参考方案1】:

我从某个我不记得的地方抄录了这段代码,但它似乎适用于从第一个有效驱动器获取序列号。抱歉,如果它不能编译,我不得不用通用的字符串类替换我们自己的字符串类。你可能想要的就是调用 GetVolumeInformation()

template <class ELT> static const ELT* NextToken(const ELT* ptr) 
    // Skip this null-terminated string
    while (*ptr != 0) 
        ptr++;
    
    ptr++;
    return ptr;

int getDiskId() 
    int bufSize = GetLogicalDriveStrings(0, 0);
    WCHAR* buffer = new WCHAR[bufSize];
    GetLogicalDriveStrings(bufSize, buffer);
    std::vector<std::string> driveStrings;
    for (const WCHAR *ptr = buffer; *ptr != 0; ptr = NextToken(ptr)) 
        if (toupper(*ptr) == 'A' || toupper(*ptr) == 'B') 
            continue;
        
        std::string tmp;
        tmp += toupper(*ptr);
        driveStrings.push_back(tmp);
    
    // want lowest letter first
    std::sort(driveStrings.begin(), driveStrings.end());
    for (int i = 0; i < driveStrings.size(); i++) 
        DWORD dummy(0);
        DWORD serialNumber(0);
        if (
            GetVolumeInformation(
                driveStrings[i].c_str(),        // lpRootPathName
                0,          // lpVolumeNameBuffer
                0,          // nVolumeNameSize
                &serialNumber,
                &dummy,     // lpMaximumComponentLength
                &dummy,     // lpFileSystemFlags
                0,          // lpFileSystemNameBuffer
                0           // nFileSystemNameSize
            )
        ) 
            break;
        
    
    delete [] buffer;
    return serialNumber;

【讨论】:

我认为这只适用于有问题的卷分配了驱动器号的特殊情况。 这也无法确定 哪个 驱动器号(如果有)属于该驱动器。它只会选择 C: 99% 的时间。此外,A: 和 B: 是合法的硬盘驱动器号。它们不是为任何事情保留的。 @AndrewMedico:嗯,我想技术上是正确的,但我真的不建议使用它们。我不想想到有多少生产代码有类似的硬编码假设。

以上是关于如何获取物理驱动器的卷 ID?的主要内容,如果未能解决你的问题,请参考以下文章

获取其中所有硬盘和分区的序列号

如何使用 WMI 检索物理打印机列表?

如何使用 mongoDb java 异步驱动程序插入 mongoDb 集合后获取 _id

如何使用旧驱动程序获取 JDBC 中插入行的 ID?

MongoDB C#驱动程序2.0:如何从MapReduceAsync获取结果

如何将挂载点的卷 GUID 转换为实际路径?