Как определить, подключен ли жесткий диск через USB?

Я пытаюсь написать небольшую программу резервного копирования для друзей и семьи и хочу, чтобы она была максимально простой в использовании. Я не хочу спрашивать пользователя, куда делать резервную копию их данных, я просто хочу найти и использовать первый жесткий диск USB, подключенный к компьютеру. Получение уникального идентификатора жесткого диска, вероятно, также будет хорошей идеей, просто как двойная проверка перед следующим запуском резервного копирования.


person Stacey Richards    schedule 20.10.2008    source источник


Ответы (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, согласно документации.

В качестве примечания, с точки зрения пользовательского интерфейса, я бы посоветовал, когда вы впервые найдете новый диск, представить его пользователю и спросить: «Это тот диск, который вы хотите использовать для резервного копирования?». В противном случае существует большая вероятность случайного удаления данных на ключе USB, который случайно был подключен. Ничто так не подрывает доверие к программе резервного копирования, как когда она уничтожает ваши данные. :)

person gregmac    schedule 21.10.2008
comment
Я предполагаю, что IO.DriveInfo - это то же самое, что GetDriveInfo в Win32 api. Если это так, он возвращает то же значение для жесткого диска USB, что и для фиксированного жесткого диска (DRIVE_FIXED). - person Stacey Richards; 21.10.2008

Я потратил немного времени на поиски и нашел функцию под названием 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;
}
person Stacey Richards    schedule 21.10.2008
comment
Если у вас есть известный файл, расположенный в известном месте на съемном диске (в корне), вы можете просмотреть все буквы дисков в поисках этого файла. Когда вы его найдете, вы узнаете букву диска. - person BoltBait; 22.10.2008

Вам необходимо использовать функцию RegisterDeviceNotification. Здесь есть несколько указаний о том, как сделать это. И еще один образец кода

Вы можете перечислить все запоминающие устройства, используя этот образец. В общем, ищите SetupDiXXX api.

Обратите внимание, что, учитывая динамический характер USB-устройств, использование механизма уведомлений является обязательным ИМХО. Вы можете обнаружить, что ваше самоанализирующее устройство уже отсоединено или отсутствует новое, которое только что прибыло.

person Ilya    schedule 21.10.2008
comment
Спасибо за указатель, но я не хочу определять, когда диск подключен или отключен, я хочу знать, является ли подключенный диск USB (может быть подключен до запуска моей программы). - person Stacey Richards; 21.10.2008

Несколько фрагментов информации можно собрать без особых проблем:

  • Используйте GetDriveType, чтобы найти первый съемный диск, проверьте, существует ли записываемый носитель (что в значительной степени исключит приводы компакт-дисков). Возможно, вам также захочется посмотреть другие строки, которые доступны при запросе информации о диске через win32.
  • Используйте libusb, чтобы узнать, где находится USB-устройство первого класса хранения (вероятно, это флэш-память или жесткий диск).
  • Эта статья о C # указывает на классы дисков Win32, к которым вы, возможно, сможете подключиться.

Отправьте свой ответ здесь, когда найдете его!

-Адам

person Adam Davis    schedule 20.10.2008
comment
Спасибо за быстрый ответ. GetDriveInfo возвращает то же значение для фиксированного жесткого диска (диск C), что и для жесткого диска UDB; DRIVE_FIXED. Я попробовал это с помощью USB-накопителя, и он сообщил, что это DRIVE_REMOVABLE. - person Stacey Richards; 21.10.2008

Я нашел в 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: дисковод является дисководом для компакт-дисков.

DRIVE_RAMDISK 6: Диск представляет собой RAM-диск.

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

person Joel    schedule 29.08.2012