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

时间:2022-10-16 07:20:58

I am trying to write a little backup program for friends and family and want it to be as simple to use a possible. I don't want to have to ask the user where to backup their data to, I just want to search for and use the first USB hard drive connected to the computer. Obtaining the unique ID of the hard drive would probably be a good idea too, just as a double check for next time the backup runs.

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

5 个解决方案

#1


1  

I know your question is tagged Win32, but this is quite simple with .NET:

我知道你的问题被标记为Win32,但这对.NET非常简单:

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

See drive.Name and drive.VolumeLabel for getting the label. You can also get the size, and make an educated guess that it's a USB stick (and a big enough one) -- Removable can mean either Floppy or USB, according to the docs.

请参阅drive.Name和drive.VolumeLabel以获取标签。根据文档,你也可以获得尺寸,并做出有根据的猜测它是一个USB棒(并且足够大) - 可移动可能意味着软盘或USB。

As a side note, from a UI perspective, I'd suggest the first time you find a new drive, present it to the user and ask "is this the drive you want to use for backups?". Otherwise, there is a big potential for accidentally wiping out data on a usb key that happened to be plugged in. Nothing destroys the credibility of a backup program like when it destroys your data. :)

作为旁注,从UI的角度来看,我建议您第一次找到新驱动器,将其呈现给用户并询问“这是您要用于备份的驱动器吗?”。否则,很有可能会意外地擦除碰巧插入的usb密钥上的数据。没有什么能破坏备份程序的可信度,就像它会破坏你的数据一样。 :)

#2


1  

I spent a little time looking around and found a function called SetupDiEnumDeviceInfo which did provide a solution to know whether a hard drive was removable or not but with that information I still can't (yet) map what I find back to a drive letter!

我花了一点时间环顾四周,发现了一个名为SetupDiEnumDeviceInfo的函数,它确实提供了一个解决方案来了解硬盘驱动器是否可移动但是有了这些信息我仍然无法(还)将我找到的内容映射回驱动器号!

Here's what I have so far (following code creates a dll):

这是我到目前为止(以下代码创建一个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;
}

#3


1  

You need to use RegisterDeviceNotification function. Here is some pointers about how to do it. And one more sample code

您需要使用RegisterDeviceNotification函数。这里有一些关于如何做的指示。还有一个示例代码

You can enumerate all mass storage devices using this sample. In General look for SetupDiXXX api's.

您可以使用此示例枚举所有大容量存储设备。一般来说,寻找SetupDiXXX api。

Please note that taking in consideration dynamic nature of usb devices, using notification mechanism is mandatory IMHO. You might find your self analyzing device that already detached or missing new device that just arrived.

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

#4


0  

A few pieces of information can be gathered without too much trouble:

可以毫不费力地收集一些信息:

  • Use GetDriveType to find the first removeable drive, test if writeable media exists (which will largely rule out CD drives). May also want to look at further strings that are available when you query the drive information via win32.
  • 使用GetDriveType查找第一个可移动驱动器,测试是否存在可写介质(这将主要排除CD驱动器)。您还可以查看通过win32查询驱动器信息时可用的其他字符串。

  • Use libusb to see where the first storage class USB device is (will likely be a flash or hard drive)
  • 使用libusb查看第一个存储类USB设备的位置(可能是闪存或硬盘)

  • This C# article points towards win32 disk drive classes you might be able to tap into.
  • 这篇C#文章指向了你可以使用的win32磁盘驱动器类。

Post your answer here when you find it!

当你找到它时,在这里发布你的答案!

-Adam

#5


0  

I found a great function in the Win32 API for testing the type of drive.

我在Win32 API中发现了一个很棒的功能来测试驱动器的类型。

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

Return values of function:

返回函数值:

DRIVE_UNKNOWN 0: The drive type cannot be determined.

DRIVE_UNKNOWN 0:无法确定驱动器类型。

DRIVE_NO_ROOT_DIR 1: The root path is invalid; for example, there is no volume mounted at the specified path.

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

DRIVE_REMOVABLE 2: The drive has removable media; for example, a floppy drive, thumb drive, or flash card reader.

DRIVE_REMOVABLE 2:驱动器具有可移动介质;例如,软盘驱动器,拇指驱动器或闪存卡读卡器。

DRIVE_FIXED 3: The drive has fixed media; for example, a hard disk drive or flash drive.

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

DRIVE_REMOTE 4: The drive is a remote (network) drive.

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

DRIVE_CDROM 5: The drive is a CD-ROM drive.

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

DRIVE_RAMDISK 6: The drive is a RAM disk.

DRIVE_RAMDISK 6:驱动器是RAM磁盘。

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

#1


1  

I know your question is tagged Win32, but this is quite simple with .NET:

我知道你的问题被标记为Win32,但这对.NET非常简单:

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

See drive.Name and drive.VolumeLabel for getting the label. You can also get the size, and make an educated guess that it's a USB stick (and a big enough one) -- Removable can mean either Floppy or USB, according to the docs.

请参阅drive.Name和drive.VolumeLabel以获取标签。根据文档,你也可以获得尺寸,并做出有根据的猜测它是一个USB棒(并且足够大) - 可移动可能意味着软盘或USB。

As a side note, from a UI perspective, I'd suggest the first time you find a new drive, present it to the user and ask "is this the drive you want to use for backups?". Otherwise, there is a big potential for accidentally wiping out data on a usb key that happened to be plugged in. Nothing destroys the credibility of a backup program like when it destroys your data. :)

作为旁注,从UI的角度来看,我建议您第一次找到新驱动器,将其呈现给用户并询问“这是您要用于备份的驱动器吗?”。否则,很有可能会意外地擦除碰巧插入的usb密钥上的数据。没有什么能破坏备份程序的可信度,就像它会破坏你的数据一样。 :)

#2


1  

I spent a little time looking around and found a function called SetupDiEnumDeviceInfo which did provide a solution to know whether a hard drive was removable or not but with that information I still can't (yet) map what I find back to a drive letter!

我花了一点时间环顾四周,发现了一个名为SetupDiEnumDeviceInfo的函数,它确实提供了一个解决方案来了解硬盘驱动器是否可移动但是有了这些信息我仍然无法(还)将我找到的内容映射回驱动器号!

Here's what I have so far (following code creates a dll):

这是我到目前为止(以下代码创建一个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;
}

#3


1  

You need to use RegisterDeviceNotification function. Here is some pointers about how to do it. And one more sample code

您需要使用RegisterDeviceNotification函数。这里有一些关于如何做的指示。还有一个示例代码

You can enumerate all mass storage devices using this sample. In General look for SetupDiXXX api's.

您可以使用此示例枚举所有大容量存储设备。一般来说,寻找SetupDiXXX api。

Please note that taking in consideration dynamic nature of usb devices, using notification mechanism is mandatory IMHO. You might find your self analyzing device that already detached or missing new device that just arrived.

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

#4


0  

A few pieces of information can be gathered without too much trouble:

可以毫不费力地收集一些信息:

  • Use GetDriveType to find the first removeable drive, test if writeable media exists (which will largely rule out CD drives). May also want to look at further strings that are available when you query the drive information via win32.
  • 使用GetDriveType查找第一个可移动驱动器,测试是否存在可写介质(这将主要排除CD驱动器)。您还可以查看通过win32查询驱动器信息时可用的其他字符串。

  • Use libusb to see where the first storage class USB device is (will likely be a flash or hard drive)
  • 使用libusb查看第一个存储类USB设备的位置(可能是闪存或硬盘)

  • This C# article points towards win32 disk drive classes you might be able to tap into.
  • 这篇C#文章指向了你可以使用的win32磁盘驱动器类。

Post your answer here when you find it!

当你找到它时,在这里发布你的答案!

-Adam

#5


0  

I found a great function in the Win32 API for testing the type of drive.

我在Win32 API中发现了一个很棒的功能来测试驱动器的类型。

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

Return values of function:

返回函数值:

DRIVE_UNKNOWN 0: The drive type cannot be determined.

DRIVE_UNKNOWN 0:无法确定驱动器类型。

DRIVE_NO_ROOT_DIR 1: The root path is invalid; for example, there is no volume mounted at the specified path.

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

DRIVE_REMOVABLE 2: The drive has removable media; for example, a floppy drive, thumb drive, or flash card reader.

DRIVE_REMOVABLE 2:驱动器具有可移动介质;例如,软盘驱动器,拇指驱动器或闪存卡读卡器。

DRIVE_FIXED 3: The drive has fixed media; for example, a hard disk drive or flash drive.

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

DRIVE_REMOTE 4: The drive is a remote (network) drive.

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

DRIVE_CDROM 5: The drive is a CD-ROM drive.

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

DRIVE_RAMDISK 6: The drive is a RAM disk.

DRIVE_RAMDISK 6:驱动器是RAM磁盘。

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