在 Windows 上区分 USB 闪存驱动器和 USB 硬盘驱动器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3390865/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 14:57:10  来源:igfitidea点击:

Differentiating between USB flash drive and USB hard drive on Windows

windowswinapiusbusb-driveusb-flash-drive

提问by user408962

I'm trying to differentiate between a USB flash drive and a USB hard drive on Windows using the Win32 API.

我正在尝试使用 Win32 API 在 Windows 上区分 USB 闪存驱动器和 USB 硬盘驱动器。

The GetDriveType()function will return DRIVE_REMOVABLE if the drive is removable, and USB flash drives are of course removable. But I'm thinking that Windows probably considers USB hard drives removable as well (unfortunately I don't have access to a USB hard drive to test it out).

GetDriveType()函数将返回DRIVE_REMOVABLE如果驱动器是可移动的,和USB闪存驱动器当然可移动的。但我认为 Windows 可能也认为 USB 硬盘驱动器是可移动的(不幸的是,我无法访问 USB 硬盘驱动器来测试它)。

Thanks in advance.

提前致谢。

回答by Andriy

If you want to determine that a device is USB device, you can open its handle and send IOCTL queries using DeviceIoControl() to get bus type a device is connected to.

如果你想确定一个设备是 USB 设备,你可以打开它的句柄并使用 DeviceIoControl() 发送 IOCTL 查询来获取设备连接到的总线类型。

EnumUsbDrivesLetters- the post is in Russian but it contains C++ source code, so the matter could be understood easily.

EnumUsbDrivesLetters-这篇文章是俄文的,但它包含 C++ 源代码,所以这件事很容易理解。

Cheers, Andriy

干杯,安德烈

回答by Marty

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  Method      OpenVolume
//  Purpose:    Open volume for removal. Change to ::CreateFile(volumeName, 0, 0, 0, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, 0);
//              if you just want to inquire if it's removable. 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

HANDLE OpenVolume(const char& driveLetter)
{
    char volumeName[8] = "";
    char* volumeFormat = "\\.\%c:";
    sprintf(volumeName, volumeFormat, driveLetter);

    HANDLE volume = ::CreateFile(volumeName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
    if (volume == INVALID_HANDLE_VALUE) return INVALID_HANDLE_VALUE;

    DWORD bytesReturned = 0;
    STORAGE_HOTPLUG_INFO Info = {0};
    if (::DeviceIoControl(volume, IOCTL_STORAGE_GET_HOTPLUG_INFO, 0, 0, &Info, sizeof(Info), &bytesReturned, NULL)) 
    {
        if (!(Info.MediaRemovable || Info.DeviceHotplug)) 
        {
            ::CloseHandle(volume);
            ::SetLastError(ERROR_INVALID_PARAMETER);
            return INVALID_HANDLE_VALUE;
        }
    }

    return volume;
}

回答by Anton Semenov

I thinks the key is drive properties, eg Cylinder count. You can use WMI interface to determine such information. Here is an example http://www.computerperformance.co.uk/vbscript/wmi_disks_physical.htm

我认为关键是驱动器属性,例如气缸数。您可以使用 WMI 接口来确定此类信息。这是一个例子http://www.computerperformance.co.uk/vbscript/wmi_disks_physical.htm

回答by monoceres

Actually windows doesn't, GetDriveType returns 3 (DRIVE_FIXED) for both my usb hard-drives.

实际上 windows 没有,GetDriveType 为我的两个 USB 硬盘驱动器返回 3 (DRIVE_FIXED)。

回答by camilohe

Windows returns DRIVE_FIXED for external USB hard drives and usually returns DRIVE_REMOVABLE for USB flash sticks. For this reason if you want to access multiple partitions on a flash memory you have to install a filter driver to tell windows it's not a DRIVE_REMOVABLE but a DRIVE_FIXED instead. Windows only "sees" the first partition on flash sticks causing a lot of trouble for ESXi boot usb stick users ;-)

Windows 为外部 USB 硬盘驱动器返回 DRIVE_FIXED,通常为 USB 闪存棒返回 DRIVE_REMOVABLE。出于这个原因,如果您想访问闪存上的多个分区,您必须安装一个过滤驱动程序来告诉 Windows 它不是 DRIVE_REMOVABLE 而是 DRIVE_FIXED。Windows 只能“看到”闪存盘上的第一个分区,这给 ESXi 引导 USB 闪存盘用户带来了很多麻烦;-)

回答by Ana Betts

http://en.wikipedia.org/wiki/SCSI_Pass_Through_Interfacewill let you send raw SCSI commands to the device - you want to send down either INQUIRY or MODE SENSE to find out what you're looking for. However, a far better alternative may be the VDS APIs, if it will provide you correct information (I'm not sure whether it will in this case)

http://en.wikipedia.org/wiki/SCSI_Pass_Through_Interface可让您向设备发送原始 SCSI 命令 - 您想发送 INQUIRY 或 MODE SENSE 以找出您要查找的内容。但是,一个更好的替代方案可能是 VDS API,如果它会为您提供正确的信息(我不确定在这种情况下是否会)

回答by Adam Robinson

The drive type is ultimately determined by the drivers; there's no fail-safe way to make the sort of determination that you're looking for.

驱动器类型最终由驱动程序决定;没有万无一失的方法可以做出您正在寻找的那种决定。

I can say, however, that while I haveseen a USB flash stick return DRIVE_FIXED, I have neverseen a normal hard drive return DRIVE_REMOVEABLE. That's not to say that it's completely impossible for that to happen, but I've never seen it.

不过,我可以说的是,虽然我已经看到了USB闪存盘的回报DRIVE_FIXED,我从来没有见过一个正常的硬盘驱动器的回报DRIVE_REMOVEABLE。这并不是说这种情况完全不可能发生,但我从未见过。

I'd say relying on those two values is probably the closest that you're going to get.

我想说依靠这两个值可能是你最接近的。