我正在尝试为朋友和家人编写一个小备份程序,并希望它尽可能简单易用。我不想问用户将他们的数据备份到哪里,我只想搜索并使用连接到计算机的第一个 USB 硬盘驱动器。获取硬盘驱动器的唯一 ID 可能也是一个好主意,就像在下次运行备份时仔细检查一样。
5 回答
我知道您的问题被标记为 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 记忆棒(并且足够大)——根据文档,可移动可能意味着软盘或 USB 。
作为旁注,从 UI 的角度来看,我建议您第一次找到新驱动器时,将其呈现给用户并询问“这是您要用于备份的驱动器吗?”。否则,很可能会意外擦除碰巧插入的 USB 密钥上的数据。没有什么比破坏您的数据更能破坏备份程序的可信度的了。:)
您需要使用RegisterDeviceNotification功能。这里有一些关于如何做到这一点的指示。还有一个示例代码
您可以使用此示例枚举所有大容量存储设备。通常寻找 SetupDiXXX api。
请注意,考虑到 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;
}
我在 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
可以毫不费力地收集一些信息:
- 使用 GetDriveType 查找第一个可移动驱动器,测试是否存在可写介质(这将在很大程度上排除 CD 驱动器)。当您通过 win32 查询驱动器信息时,可能还想查看更多可用的字符串。
- 使用 libusb 查看第一个存储类 USB 设备在哪里(可能是闪存或硬盘驱动器)
- 这篇C# 文章指向您可能能够利用的 win32 磁盘驱动器类。
找到答案后在这里发布您的答案!
-亚当