Как перечислить физические диски в Windows?
Чтобы получить список доступных "\\\\.\PhysicalDrive0"
.
Как перечислить физические диски?
Ответ 1
WMIC
wmic - очень полный инструмент
wmic diskdrive list
предоставить (слишком много) подробный список, например
для меньшего количества информации
wmic diskdrive list brief
С
Себастьян Годеле упоминает в комментариях:
В С:
system("wmic diskdrive list");
Как уже отмечалось, вы также можете вызвать WinAPI, но... как показано в разделе " Как получить данные из WMI с помощью приложения C? ", Это довольно сложно (и обычно выполняется с C++, а не с C).
PowerShell
Или с PowerShell:
Get-WmiObject Win32_DiskDrive
Ответ 2
Один из способов сделать это:
-
Перечислить логические диски с помощью
GetLogicalDrives
-
Для каждого логического диска откройте файл с именем
"\\.\X:"
(без кавычек), где X является буквой логического диска. -
Позвоните
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
Ответ 3
Это может быть на 5 лет слишком поздно:). Но пока я не вижу ответа на это, добавив это.
Мы можем использовать API установки, чтобы получить список дисков, т.е. устройств в системе, реализующих GUID_DEVINTERFACE_DISK
.
Как только у нас появятся пути к ним, мы можем выпустить IOCTL_STORAGE_GET_DEVICE_NUMBER
для построения "\\.\PHYSICALDRIVE%d"
с помощью STORAGE_DEVICE_NUMBER.DeviceNumber
См. также SetupDiGetClassDevs
функция
#include <Windows.h>
#include <Setupapi.h>
#include <Ntddstor.h>
#pragma comment( lib, "setupapi.lib" )
#include <iostream>
#include <string>
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;
}
Ответ 4
Я изменил программу с открытым исходным кодом под названием "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
Ответ 5
Ответ намного проще, чем все приведенные выше ответы. Список физических дисков фактически хранится в ключе реестра, который также дает сопоставление устройства.
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\диск\Enum
Подсчет - это число PhysicalDrive #, и каждое нумерованное значение реестра - это соответствующий физический диск.
Например, значение реестра "0" - это PhysicalDrive0. Значение - это фактическое устройство, на которое отображается физический диск. Значение, содержащееся здесь, можно передать в CM_Locate_DevNode в параметре pDeviceID, чтобы использовать сервисы plug and play. Это позволит вам собрать массу информации на устройстве. Например, свойства диспетчера устройств, такие как "Friendly Display Name", если вам нужно имя для диска, серийные номера и т.д.
Нет необходимости в услугах WMI, которые могут не выполняться в системе или других хакерах, и эта функциональность присутствует в Windows с по меньшей мере 2000 и продолжает выполняться в Windows 10.
Ответ 6
Единственный верный способ сделать это - вызвать CreateFile()
на всех \\.\Physicaldiskx
, где x - от 0 до 15 (16 - максимальное количество разрешенных дисков). Проверьте возвращаемое значение дескриптора. Если недействительная проверка GetLastError()
для ERROR_FILE_NOT_FOUND. Если он возвращает что-то еще, то диск существует, но вы по какой-то причине не можете получить к нему доступ.
Ответ 7
GetLogicalDrives() перечисляет все смонтированные разделы диска, физические жесткие диски не.
Вы можете перечислить буквы дисков с (или без) GetLogicalDrives, а затем вызвать QueryDosDevice(), чтобы узнать, к какому физическому диску будет привязана буква.
Кроме того, вы можете декодировать информацию в реестре по HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices. Однако кодировки двоичных данных там не очевидны. Если у вас есть экземпляр книги Руссиновича и Соломона о Microsoft Windows Internals, этот куст реестра обсуждается в главе 10.
Ответ 8
Единственный правильный ответ - тот, что был @Grodriguez, и вот код, который он слишком ленил, чтобы написать:
#include <windows.h>
#include <iostream>
#include <bitset>
#include <vector>
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<char> 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
для этой задачи.
Ответ 9
Thic комбинация команд WMIC работает нормально:
wmic volume list brief
Ответ 10
Возможно, вы захотите включить старые диски A: и B: поскольку вы никогда не знаете, кто их может использовать! Я устал от USB-накопителей, натыкающихся на два диска SDHC, которые предназначены только для Readyboost. Я назначил их Высоким буквам Z: Y: с помощью утилиты, которая будет назначать буквы дисков устройствам по вашему желанию. Я задавался вопросом... Могу ли я сделать букву с буквой A:? ДА! Могу ли я поставить вторую букву диска SDHC как B:? ДА!
Я использовал флоппи-дисководы в тот же день, никогда не думал, что A: или B: пригодится Readyboost.
Моя точка зрения, не предполагайте, что A: и B: никого не будет использовать Вы даже можете найти старую команду SUBST!
Ответ 11
Я просто столкнулся с этим в своем RSS Reader сегодня. У меня есть более чистое решение для вас. Этот пример находится в Delphi, но его можно легко преобразовать в 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;
Ответ 12
Если вам нужен "физический" доступ, мы разрабатываем этот API, который в конечном итоге позволит вам общаться с устройствами хранения. Это с открытым исходным кодом, и вы можете увидеть текущий код для получения некоторой информации. Проверьте наличие дополнительных возможностей: https://github.com/virtium/vtStor
Ответ 13
Здесь - это новое решение делать это с помощью вызовов WMI.
Тогда все, что вам нужно сделать, это просто позвонить:
queryAndPrintResult(L"SELECT * FROM Win32_DiskDrive", L"Name");
Ответ 14
Составьте список всех букв в английском алфавите на английском языке, пропустив a и b. "CDEFGHIJKLMNOPQRSTUVWXYZ". Откройте каждый из этих дисков с помощью CreateFile
, например. CreateFile("\\.\C:")
. Если он не возвращает INVALID_HANDLE_VALUE
, тогда вы получите "хороший" диск. Затем возьмите этот дескриптор и запустите его через DeviceIoControl
, чтобы получить диск #. Подробнее см. мой ответ.