Intereting Posts
как предоставить более одного файла c в качестве входа в GNU Cflow? Полный C ++ i18n gettext () Пример «привет мир» Параметры Python и произвольной командной строки Удаление первого и последнего символов из строки в пакетном файле Windows Переименуйте файлы в нескольких каталогах на имя каталога Не удается установить ggplot с anaconda Портативный способ получить размер файла (в байтах) в оболочке? AngularJS + Sailsjs + Nginx = неверная дата с UTC `require ‘: нет такого файла для загрузки – mkmf (LoadError) Есть ли приятные звуковые сигналы sound32 (встроенный звуковой сигнал)? Что может заставить мою программу не использовать все ядра через некоторое время? Найти текущее количество открытых дескрипторов файлов (NOT lsof) Rails на сервере Ubuntu 14.04, а не загрузка макета приложения Использует ли веб-сервер, например Lighttpd и nginx, в большинстве случаев только преждевременную оптимизацию? error_log для виртуального хоста?

Как перечислить физические диски?

Как перечислить физические диски в Windows? Чтобы получить список доступных "\\\\.\PhysicalDrive0" .

WMIC

wmic – очень полный инструмент

 wmic diskdrive list 

предоставить (слишком большой) подробный список, например

за меньшую информацию

 wmic diskdrive list brief 

С

Себастьян Годеле упоминает в комментариях :

В C:

 system("wmic diskdrive list"); 

PowerShell

Или с PowerShell:

 Get-WmiObject Win32_DiskDrive 

Один из способов сделать это:

  1. Перечислить логические диски с помощью GetLogicalDrives

  2. Для каждого логического диска откройте файл с именем "\\.\X:" (без кавычек), где X – буква логического диска.

  3. Вызовите DeviceIoControl передав дескриптор файлу, открытому на предыдущем шаге, и параметр dwIoControlCode установлен на IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS :

     HANDLE hHandle; VOLUME_DISK_EXTENTS diskExtents; DWORD dwSize; [...] iRes = DeviceIoControl( hHandle, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, (LPVOID) &diskExtents, (DWORD) sizeof(diskExtents), (LPDWORD) &dwSize, NULL); 

Это возвращает информацию о физическом местоположении логического тома в виде структуры VOLUME_DISK_EXTENTS .

В простом случае, когда том находится на одном физическом диске, номер физического диска доступен в diskExtents.Extents[0].DiskNumber

Это может быть на 5 лет слишком поздно :). Но пока я не вижу ответа на это, добавив это.

Мы можем использовать Setup API для получения списка дисков, т. GUID_DEVINTERFACE_DISK Устройств в системе, реализующих GUID_DEVINTERFACE_DISK .

После того, как у нас есть пути к ним, мы можем выпустить IOCTL_STORAGE_GET_DEVICE_NUMBER чтобы построить "\\.\PHYSICALDRIVE%d" с STORAGE_DEVICE_NUMBER.DeviceNumber

См. Также функцию SetupDiGetClassDevs

 #include  #include  #include  #pragma comment( lib, "setupapi.lib" ) #include  #include  using namespace std; #define START_ERROR_CHK() \ DWORD error = ERROR_SUCCESS; \ DWORD failedLine; \ string failedApi; #define CHK( expr, api ) \ if ( !( expr ) ) { \ error = GetLastError( ); \ failedLine = __LINE__; \ failedApi = ( api ); \ goto Error_Exit; \ } #define END_ERROR_CHK() \ error = ERROR_SUCCESS; \ Error_Exit: \ if ( ERROR_SUCCESS != error ) { \ cout < < failedApi << " failed at " << failedLine << " : Error Code - " << error << endl; \ } int main( int argc, char **argv ) { HDEVINFO diskClassDevices; GUID diskClassDeviceInterfaceGuid = GUID_DEVINTERFACE_DISK; SP_DEVICE_INTERFACE_DATA deviceInterfaceData; PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData; DWORD requiredSize; DWORD deviceIndex; HANDLE disk = INVALID_HANDLE_VALUE; STORAGE_DEVICE_NUMBER diskNumber; DWORD bytesReturned; START_ERROR_CHK(); // // Get the handle to the device information set for installed // disk class devices. Returns only devices that are currently // present in the system and have an enabled disk device // interface. // diskClassDevices = SetupDiGetClassDevs( &diskClassDeviceInterfaceGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE ); CHK( INVALID_HANDLE_VALUE != diskClassDevices, "SetupDiGetClassDevs" ); ZeroMemory( &deviceInterfaceData, sizeof( SP_DEVICE_INTERFACE_DATA ) ); deviceInterfaceData.cbSize = sizeof( SP_DEVICE_INTERFACE_DATA ); deviceIndex = 0; while ( SetupDiEnumDeviceInterfaces( diskClassDevices, NULL, &diskClassDeviceInterfaceGuid, deviceIndex, &deviceInterfaceData ) ) { ++deviceIndex; SetupDiGetDeviceInterfaceDetail( diskClassDevices, &deviceInterfaceData, NULL, 0, &requiredSize, NULL ); CHK( ERROR_INSUFFICIENT_BUFFER == GetLastError( ), "SetupDiGetDeviceInterfaceDetail - 1" ); deviceInterfaceDetailData = ( PSP_DEVICE_INTERFACE_DETAIL_DATA ) malloc( requiredSize ); CHK( NULL != deviceInterfaceDetailData, "malloc" ); ZeroMemory( deviceInterfaceDetailData, requiredSize ); deviceInterfaceDetailData->cbSize = sizeof( SP_DEVICE_INTERFACE_DETAIL_DATA ); CHK( SetupDiGetDeviceInterfaceDetail( diskClassDevices, &deviceInterfaceData, deviceInterfaceDetailData, requiredSize, NULL, NULL ), "SetupDiGetDeviceInterfaceDetail - 2" ); disk = CreateFile( deviceInterfaceDetailData->DevicePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); CHK( INVALID_HANDLE_VALUE != disk, "CreateFile" ); CHK( DeviceIoControl( disk, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &diskNumber, sizeof( STORAGE_DEVICE_NUMBER ), &bytesReturned, NULL ), "IOCTL_STORAGE_GET_DEVICE_NUMBER" ); CloseHandle( disk ); disk = INVALID_HANDLE_VALUE; cout < < deviceInterfaceDetailData->DevicePath < < endl; cout << "\\\\?\\PhysicalDrive" << diskNumber.DeviceNumber << endl; cout << endl; } CHK( ERROR_NO_MORE_ITEMS == GetLastError( ), "SetupDiEnumDeviceInterfaces" ); END_ERROR_CHK(); Exit: if ( INVALID_HANDLE_VALUE != diskClassDevices ) { SetupDiDestroyDeviceInfoList( diskClassDevices ); } if ( INVALID_HANDLE_VALUE != disk ) { CloseHandle( disk ); } return error; } 

Я изменил программу с открытым исходным кодом под названием «dskwipe», чтобы вытащить эту информацию из этого диска. Dskwipe написан на C, и вы можете вытащить эту функцию из него. Бинарные и источники доступны здесь: dskwipe 0.3 был выпущен

Возвращенная информация будет выглядеть примерно так:

 Device Name Size Type Partition Type ------------------------------ --------- --------- -------------------- \\.\PhysicalDrive0 40.0 GB Fixed \\.\PhysicalDrive1 80.0 GB Fixed \Device\Harddisk0\Partition0 40.0 GB Fixed \Device\Harddisk0\Partition1 40.0 GB Fixed NTFS \Device\Harddisk1\Partition0 80.0 GB Fixed \Device\Harddisk1\Partition1 80.0 GB Fixed NTFS \\.\C: 80.0 GB Fixed NTFS \\.\D: 2.1 GB Fixed FAT32 \\.\E: 40.0 GB Fixed NTFS 

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

HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services \ диск \ Enum

Count – это число PhysicalDrive #, и каждое числовое значение реестра – это соответствующий физический диск.

Например, значение реестра «0» – это PhysicalDrive0. Значение – это фактическое устройство, на которое отображается физический диск. Значение, содержащееся здесь, может быть передано в CM_Locate_DevNode в параметре pDeviceID для использования сервисов plug and play. Это позволит вам собрать массу информации на устройстве. Например, свойства диспетчера устройств, такие как «Friendly Display Name», если вам нужно имя для диска, серийные номера и т. Д.

Нет необходимости в услугах WMI, которые могут не выполняться в системе или в других хакерах, и эта функциональность присутствует в Windows с по меньшей мере 2000 и продолжает иметь место в Windows 10.

Единственный верный способ сделать это – вызвать CreateFile() на всех \\.\Physicaldiskx где x от 0 до 15 (16 – максимальное количество разрешенных дисков). Проверьте возвращаемое значение дескриптора. Если неверно проверить GetLastError() для ERROR_FILE_NOT_FOUND . Если он возвращает что-то еще, то диск существует, но по какой-то причине вы не можете получить к нему доступ.

GetLogicalDrives () перечисляет все установленные разделы диска, а не физические диски.

Вы можете перечислять буквы дисков с (или без) GetLogicalDrives, а затем вызвать QueryDosDevice (), чтобы узнать, к какому физическому диску сопоставляется буква.

Кроме того, вы можете декодировать информацию в реестре по HKEY_LOCAL_MACHINE \ SYSTEM \ MountedDevices. Однако кодировки двоичных данных там не очевидны. Если у вас есть копия книги Русиновича и Соломона «Внутренние документы Microsoft Windows», этот куст реестра обсуждается в главе 10.

Единственным правильным ответом является тот, который @Grodriguez, и вот код, который он слишком ленив, чтобы написать:

 #include  #include  #include  #include  using namespace std; typedef struct _DISK_EXTENT { DWORD DiskNumber; LARGE_INTEGER StartingOffset; LARGE_INTEGER ExtentLength; } DISK_EXTENT, *PDISK_EXTENT; typedef struct _VOLUME_DISK_EXTENTS { DWORD NumberOfDiskExtents; DISK_EXTENT Extents[ANYSIZE_ARRAY]; } VOLUME_DISK_EXTENTS, *PVOLUME_DISK_EXTENTS; #define CTL_CODE(DeviceType, Function, Method, Access) \ (((DeviceType) < < 16) | ((Access) << 14) | ((Function) << 2) | (Method)) #define IOCTL_VOLUME_BASE ((DWORD)'V') #define METHOD_BUFFERED 0 #define FILE_ANY_ACCESS 0x00000000 #define IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS CTL_CODE(IOCTL_VOLUME_BASE, 0, METHOD_BUFFERED, FILE_ANY_ACCESS) int main() { bitset<32> drives(GetLogicalDrives()); vector goodDrives; for (char c = 'A'; c < = 'Z'; ++c) { if (drives[c - 'A']) { if (GetDriveType((c + string(":\\")).c_str()) == DRIVE_FIXED) { goodDrives.push_back(c); } } } for (auto & drive : goodDrives) { string s = string("\\\\.\\") + drive + ":"; HANDLE h = CreateFileA( s.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_RANDOM_ACCESS, NULL ); if (h == INVALID_HANDLE_VALUE) { cerr << "Drive " << drive << ":\\ cannot be opened"; continue; } DWORD bytesReturned; VOLUME_DISK_EXTENTS vde; if (!DeviceIoControl( h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, &vde, sizeof(vde), &bytesReturned, NULL )) { cerr << "Drive " << drive << ":\\ cannot be mapped into physical drive"; continue; } cout << "Drive " << drive << ":\\ is on the following physical drives: "; for (int i = 0; i < vde.NumberOfDiskExtents; ++i) { cout << vde.Extents[i].DiskNumber << ' '; } cout << endl; } } 

Я думаю, что установка набора драйверов для Windows - довольно длительный процесс, поэтому я включил декларации, которые нужно использовать для этого решения DeviceIoControl .

Тесная комбинация команд WMIC работает нормально:

 wmic volume list brief 

Можете добавить старые диски A: и B: как вы никогда не знаете, кто их сможет использовать! Я устал от USB-накопителей, натыкающихся на два диска SDHC, которые предназначены только для Readyboost. Я назначил их Высоким буквам Z: Y: с помощью утилиты, которая будет назначать буквы дисков устройствам по вашему желанию. Я задавался вопросом … Могу ли я сделать букву с буквой A:? ДА! Могу ли я поставить вторую букву диска SDHC как B:? ДА!

Я использовал флоппи-дисководы в тот же день, никогда не думал, что A: или B: пригодится для Readyboost.

Я хочу сказать, не предполагайте, что A: & B: ни для кого не будет использоваться. Вы даже можете найти старую команду SUBST!

Я просто столкнулся с этим в своем RSS Reader сегодня. У меня есть более чистое решение для вас. Этот пример находится в Delphi, но может быть легко преобразован в C / C ++ (это все Win32).

Запросить имена всех значений из следующего раздела реестра: HKLM \ SYSTEM \ MountedDevices

Один за другим передайте их в следующую функцию, и вам будет возвращено имя устройства. Довольно чисто и просто! Я нашел этот код в блоге здесь.

 function VolumeNameToDeviceName(const VolName: String): String; var s: String; TargetPath: Array[0..MAX_PATH] of WideChar; bSucceeded: Boolean; begin Result := ”; // VolumeName has a format like this: \\?\Volume{c4ee0265-bada-11dd-9cd5-806e6f6e6963}\ // We need to strip this to Volume{c4ee0265-bada-11dd-9cd5-806e6f6e6963} s := Copy(VolName, 5, Length(VolName) - 5); bSucceeded := QueryDosDeviceW(PWideChar(WideString(s)), TargetPath, MAX_PATH) <> 0; if bSucceeded then begin Result := TargetPath; end else begin // raise exception end; end; 

Если вам нужен «физический» доступ, мы разрабатываем этот API, который в конечном итоге позволит вам общаться с устройствами хранения. Это с открытым исходным кодом, и вы можете увидеть текущий код для получения некоторой информации. Проверьте наличие дополнительных возможностей: https://github.com/virtium/vtStor

Вот новое решение для выполнения WMI-вызовов.
Тогда все, что вам нужно сделать, это просто позвонить:

 queryAndPrintResult(L"SELECT * FROM Win32_DiskDrive", L"Name"); 

Составьте список всех букв в английском алфавите, пропуская a & b. “CDEFGHIJKLMNOPQRSTUVWXYZ”. Откройте каждый из этих дисков с помощью CreateFile например CreateFile("\\.\C:") . Если он не возвращает INVALID_HANDLE_VALUE тогда вы получите «хороший» диск. Затем возьмите этот дескриптор и запустите его через DeviceIoControl чтобы получить диск #. См. Мой ответ для получения более подробной информации .