如何检测硬盘是否通过USB连接?

问题描述:

我正在尝试为朋友和家人编写一个小小的备份程序,并希望它能够像使用可能的一样简单。我不想问用户在哪里备份数据,我只想搜索并使用连接到计算机的第一个USB硬盘驱动器。获得硬盘驱动器的唯一ID也可能是一个好主意,就像下次备份运行时的双重检查一样。如何检测硬盘是否通过USB连接?

我花了一点时间四处看看,发现一个名为SetupDiEnumDeviceInfo的函数,它确实提供了一个解决方案,以了解硬盘驱动器是否可移除,但有了这些信息,我仍然不能(映射)我找回的东西一个盘符!

这里是我到目前为止(以下代码创建一个DLL):

#include "stdafx.h" 
#include <setupapi.h> 
#include <devguid.h> 
#include <cfgmgr32.h> 
extern "C" __declspec(dllexport) int usb_hard_drives() { 
    HDEVINFO hdevinfo = SetupDiGetClassDevs(&GUID_DEVCLASS_DISKDRIVE, NULL, NULL, DIGCF_PRESENT); 
    if (hdevinfo == INVALID_HANDLE_VALUE) return -1; 
    DWORD MemberIndex = 0; 
    SP_DEVINFO_DATA sp_devinfo_data; 
    ZeroMemory(&sp_devinfo_data, sizeof(sp_devinfo_data)); 
    sp_devinfo_data.cbSize = sizeof(sp_devinfo_data); 
    int c = 0; 
    while (SetupDiEnumDeviceInfo(hdevinfo, MemberIndex, &sp_devinfo_data)) { 
    DWORD PropertyRegDataType; 
    DWORD RequiredSize; 
    DWORD PropertyBuffer; 
    if (SetupDiGetDeviceRegistryProperty(hdevinfo, &sp_devinfo_data, SPDRP_CAPABILITIES, &PropertyRegDataType, (PBYTE)&PropertyBuffer, sizeof(PropertyBuffer), &RequiredSize)) { 
     if (PropertyBuffer && CM_DEVCAP_REMOVABLE == CM_DEVCAP_REMOVABLE) { 
     // do something here to identify the drive letter. 
     c++; 
     } 
    }  
    MemberIndex++; 
    } 
    SetupDiDestroyDeviceInfoList(hdevinfo); 
    return c; 
} 
+0

如果已知文件位于可移动驱动器(根)上的已知位置,则可以遍历所有寻找该文件的驱动器盘符。当你找到它时,你就知道盘符。 – BoltBait 2008-10-21 22:42:01

的一些信息可以收集没有太多的麻烦:

  • 使用GetDriveType找到第一个可拆卸的驱动,测试,如果重写媒体存在(这将在很大程度上排除CD驱动器)。也可能要查看通过win32查询驱动器信息时可用的更多字符串。
  • 使用libusb查看第一个存储级别USB设备的位置(可能是闪存或硬盘驱动器)
  • C# article指向您可能能够使用的win32磁盘驱动器类。

这里后你的答案,当你找到它!

- 亚当

+0

感谢您的快速响应。 GetDriveInfo为固定硬盘驱动器(驱动器C)返回与UDB硬盘驱动器相同的值; DRIVE_FIXED。我用USB笔驱动器试过,并将其报告为DRIVE_REMOVABLE。 – 2008-10-21 10:41:45

我知道你的问题是标签的Win32,但这是.NET很简单:

foreach (IO.DriveInfo drive in IO.DriveInfo.GetDrives()) { 
    if ((drive.DriveType == IO.DriveType.Removable)) { 
    // this is a removable drive 
    } 
} 

见drive.Name和drive.VolumeLabel用于获取标签。你也可以得到它的大小,并据此猜测它是一个USB棒(并且足够大) - 可移动可以指Floppy或USB,according to the docs

作为一个侧面说明,从UI的角度来看,我建议你第一次找到新的驱动器,它呈现给用户,并问:“这是你要用于备份的驱动器?”。否则,意外清除偶然插入的USB密钥上的数据的可能性很大。没有什么能够破坏备份程序的可信度,就像它破坏数据时一样。 :)

+1

我假设IO.DriveInfo与Win32 API中的GetDriveInfo相同。如果是这样,它会为USB硬盘驱动器返回与固定硬盘驱动器(DRIVE_FIXED)相同的值。 – 2008-10-21 10:43:35

您需要使用RegisterDeviceNotification功能。 Here是一些关于如何去做的指针。还有一sample code

您可以枚举使用this样品的所有大容量存储设备。一般来看看SetupDiXXX api的。

请注意,考虑到USB设备的动态性质,使用通知机制是强制性的恕我直言。您可能会发现您的自分析设备已经分离或丢失刚刚到达的新设备。

+0

感谢您的指针,但我不想检测驱动器何时连接或断开连接,我想知道连接的驱动器是否是USB驱动器(可能会在我的程序启动之前插入)。 – 2008-10-21 10:46:16

我发现Win32 API中一个伟大的功能测试驱动器的类型。

if(2 == ::getDriveType(<driveletter>)){ 
    // its removable 
} 

的函数返回值:

DRIVE_UNKNOWN 0:驱动器类型不能被确定。

DRIVE_NO_ROOT_DIR 1:根路径无效;例如,在指定的路径上没有安装卷。

DRIVE_REMOVABLE 2:驱动器有可移动媒体;例如,软盘驱动器,拇指驱动器或闪存卡读取器。

DRIVE_FIXED 3:驱动器有固定介质;例如,硬盘驱动器或闪存驱动器。

DRIVE_REMOTE 4:驱动器是远程(网络)驱动器。

DRIVE_CDROM 5:驱动器是CD-ROM驱动器。

DRIVE_RAMDISK 6:驱动器是RAM磁盘。

http://msdn.microsoft.com/en-us/library/windows/desktop/aa364939(v=vs.85).aspx