Подтвердить что ты не робот

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

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

4b9b3361

Ответ 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, чтобы получить диск #. Подробнее см. мой ответ.