C++ 获取卷列表时总是显示C:\

C++ 获取卷列表时总是显示C:\,c++,winapi,qt,visual-c++,C++,Winapi,Qt,Visual C++,为什么下面的代码总是报告C:\尽管它报告不同的设备名称 handle = FindFirstVolumeW(volName, sizeof(volName)); do{ wchar_t wVolName[MAX_PATH]; QString::fromWCharArray(volName).toWCharArray(wVolName);//make a copy of volName on wVolName wVolName[wcslen(volName)-1]

为什么下面的代码总是报告C:\尽管它报告不同的设备名称

  handle = FindFirstVolumeW(volName, sizeof(volName));
  do{
    wchar_t wVolName[MAX_PATH];
    QString::fromWCharArray(volName).toWCharArray(wVolName);//make a copy of volName on wVolName
    wVolName[wcslen(volName)-1] = L'\0';
    wchar_t wDeviceName[MAX_PATH];
    int charCount = 0;
    charCount = QueryDosDeviceW(&wVolName[4], wDeviceName, ARRAYSIZE(wDeviceName));

    qDebug() << QString::fromWCharArray(wVolName) << "Device: " << QString::fromWCharArray(wDeviceName);//print wVolName and wDeviceName

    wchar_t driveName[MAX_PATH];
    GetVolumePathName(wDeviceName, driveName, MAX_PATH);
    CloseHandle(handle);

    qDebug() << QString::fromWCharArray(driveName);

  }while(FindNextVolume(handle, volName, sizeof(volName)));
  FindVolumeClose(handle);
为什么它不报告D、E等

编辑


我如何推导分配给卷的驱动器号函数的文档说明了一切:

必须指定有效的Win32命名空间路径。如果指定NT命名空间路径,例如,\DosDevices\H:或\Device\HardDiskVolume6,则函数将返回当前卷的驱动器号,而不是该NT命名空间路径的驱动器号


顺便说一句,一个卷可以装载到多个驱动器号。像C:这样的驱动器名只不过是NT名称空间中的一个符号链接,因此以这种方式进行转换是没有意义的。

函数的文档说明了这一切:

必须指定有效的Win32命名空间路径。如果指定NT命名空间路径,例如,\DosDevices\H:或\Device\HardDiskVolume6,则函数将返回当前卷的驱动器号,而不是该NT命名空间路径的驱动器号


顺便说一句,一个卷可以装载到多个驱动器号。驱动器名如C:在NT名称空间中只不过是一个符号链接,因此以这种方式转换是没有意义的。

可能是因为您在循环中调用CloseHandle:不要这样做


看起来您的代码是在以下情况下建模的:您会注意到他们调用CloseHandle的唯一时间是在整个循环完成之后。

可能是因为您在循环中调用CloseHandle:不要这样做

看起来您的代码是在以下时间建模的:您会注意到他们调用CloseHandle的唯一时间是在整个循环完成之后。

来自:

如果指定相对目录或文件名而不指定卷 限定符GetVolumePathName返回当前卷的驱动器号 音量

从:

如果指定相对目录或文件名而不指定卷 限定符GetVolumePathName返回当前卷的驱动器号 音量



是否检查GetVolumePathName是否成功?它是否返回错误或成功代码?因为\Device\HarddiskVolume2可能会根据当前目录解析为C:\Device\HarddiskVolume2。事实上,它已写入文档中:您必须指定有效的Win32命名空间路径。如果指定一个NT命名空间路径,例如,\DosDevices\H:或\Device\HardDiskVolume6,该函数将返回当前卷的驱动器号,而不是该NT命名空间路径的驱动器号。@无用:Y我已选中。它返回1。我只是为了简要说明代码而省略了它。@avakar:那么我需要做些什么来防止它以这种方式播放,并在'C:\`'前面加上前缀?您是否检查了GetVolumePathName是否成功?它是否返回错误或成功代码?因为\Device\HarddiskVolume2可能会根据当前目录解析为C:\Device\HarddiskVolume2。事实上,它已写入文档中:您必须指定有效的Win32命名空间路径。如果指定一个NT命名空间路径,例如,\DosDevices\H:或\Device\HardDiskVolume6,该函数将返回当前卷的驱动器号,而不是该NT命名空间路径的驱动器号。@无用:Y我已选中。它返回1。我只是为了简要说明代码而省略了它。@avakar:那么我需要做什么来防止它以这种方式播放,在'C:\`前面加上前缀?是的,我根据它和你提供的链接进行了建模。但是如果它是一种值未刷新的问题,为什么设备名称会更改?是的,我根据它和你提供的链接进行了建模。但是如果它是一种值未刷新的问题,那么关于为什么设备名称会更改的问题,那么我需要做什么,使其不会始终返回当前卷?@NeelBasu,使用GetVolumePathNamesForVolumeName,而不是使用wVolName作为参数。是的,伙计!!它起作用了。但还有一个问题。它说的是GetVolumePathNames,所以如果有多个地方安装了它,它的行为会如何呢?哦!我知道了,列表是一个以空结尾的字符串数组,由一个附加的空字符终止。但是我必须说这是一个非常糟糕的设计,那么我需要做什么,使它不会始终返回当前卷?@NeelBasu,使用GetVolumePathNamesForVolumeName,而不是使用wVolName作为参数。是的,伙计!!它起作用了。但还有一个问题。它说的是GetVolumePathNames,所以如果有多个地方安装了它,它的行为会如何呢?哦!我知道了,列表是一个以空结尾的字符串数组,由一个附加的空字符终止。但是我必须说这是一个非常糟糕的设计,那么我需要做什么,这样它就不会总是返回当前卷?@NeelBasu,你可以检查所有的驱动器号,将它们解析到NT path,然后进行比较。这将是一种蛮力。我想避免野蛮的ForcingOne或其他方式,你必须通过所有的符号链接。设备对象上没有反向引用列表。那么我需要做什么,使它不会始终返回当前卷?@NeelBasu,
你可以检查所有的驱动器号,将它们解析为NT路径,然后进行比较。这将是一种蛮力。我想避免野蛮的ForcingOne或其他方式,你必须通过所有的符号链接。设备对象上没有反向引用列表。
"\\?\Volume{5c77cc58-d5ab-11e0-a0ec-806d6172696f}" Device:  "\Device\HarddiskVolume2" 
"C:\" 
"\\?\Volume{5c77cc59-d5ab-11e0-a0ec-806d6172696f}" Device:  "\Device\HarddiskVolume3" 
"C:\" 
"\\?\Volume{5c77cc57-d5ab-11e0-a0ec-806d6172696f}" Device:  "\Device\CdRom0" 
"C:\" 
"\\?\Volume{5c77cc56-d5ab-11e0-a0ec-806d6172696f}" Device:  "\Device\Floppy0" 
"C:\" 
"\\?\Volume{8d974f2c-e9a1-11e0-b7da-0013d407432f}" Device:  "\Device\Harddisk1\DP(1)0-    0+8" 
"C:\"