Как перечислить физические диски? - PullRequest
68 голосов
/ 29 ноября 2008

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

Ответы [ 14 ]

63 голосов
/ 29 ноября 2008

WMIC

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

wmic diskdrive list

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

для меньшего количества информации

wmic diskdrive list brief 

C

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

В С:

system("wmic diskdrive list");

Как прокомментировано, вы также можете вызвать WinAPI, но ... как показано в " Как получить данные из WMI с помощью приложения C? ", это довольно сложно (и обычно выполняется с C ++ не С).

PowerShell

Или с PowerShell:

Get-WmiObject Win32_DiskDrive
41 голосов
/ 27 июля 2012

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

  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

27 голосов
/ 12 августа 2013

Это может быть на 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;
}
13 голосов
/ 20 мая 2016

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

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

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

Например, значением реестра «0» является PhysicalDrive0. Значение - это фактическое устройство, которому сопоставлен PhysicalDrive0. Содержащееся здесь значение может быть передано в CM_Locate_DevNode в параметре pDeviceID для использования сервисов Plug and Play. Это позволит вам собрать множество информации на устройстве. Такие как свойства из диспетчера устройств, такие как «Дружественное отображаемое имя», если вам нужно имя для диска, серийные номера и т. Д.

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

12 голосов
/ 08 декабря 2008

Я изменил программу с открытым исходным кодом под названием "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
9 голосов
/ 19 апреля 2012

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

8 голосов
/ 17 февраля 2015

Единственный правильный ответ - ответ @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 Driver Development Kit довольно длительный процесс, поэтому я включил декларации, необходимые для использования DeviceIoControl для этой задачи.

8 голосов
/ 29 ноября 2008

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

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

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

2 голосов
/ 01 января 2014

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

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

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

2 голосов
/ 21 июня 2013

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

wmic volume list brief
...