90 votes

Comment dresser la liste des disques physiques ?

Comment dresser la liste des disques physiques dans Windows ? Pour obtenir une liste des "\\\\.\PhysicalDrive0" disponible.

84voto

VonC Points 414372

WMIC wmic est un outil très complet

wmic diskdrive list

fournir une liste (trop) détaillée, par exemple

pour moins d'informations

wmic diskdrive list brief 

C Sebastian Godelet mentions dans les commentaires :

En C :

system("wmic diskdrive list");

Comme indiqué, vous pouvez également appeler la WinAPI, mais... comme indiqué dans " Comment obtenir des données de WMI à l'aide d'une application C ? "Il s'agit d'une opération assez complexe (et généralement réalisée en C++, et non en C).


PowerShell Ou avec PowerShell :

Get-WmiObject Win32_DiskDrive

Mise à jour février 2022, Microsoft annonce dans " Les fonctionnalités de Windows 10 que nous ne développons plus "

L'outil WMIC est obsolète dans Windows 10, la version 21H1 et la version 21H1 General Availability Channel de Windows Server.

Cet outil est remplacé par Windows PowerShell pour WMI .

Note : Cette dépréciation ne s'applique qu'à l'option outil de gestion en ligne de commande . WMI lui-même n'est pas affecté.

15 votes

-1 Ne répond pas à la question, qui est de savoir comment le faire en C.

13 votes

+1 Ne répond pas à la question, mais c'est une information très utile :-)

8 votes

Vous pourriez faire une system("wmic diskdrive list"); en C

52voto

Grodriguez Points 9945

Une façon de procéder :

  1. Énumérer les lecteurs logiques à l'aide de GetLogicalDrives

  2. Pour chaque lecteur logique, ouvrez un fichier nommé "\\.\X:" (sans les guillemets) où X est la lettre du lecteur logique.

  3. Llame a DeviceIoControl en passant l'identifiant du fichier ouvert à l'étape précédente, et la fonction dwIoControlCode paramètre réglé sur 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);

Cette fonction renvoie des informations sur l'emplacement physique d'un volume logique, sous la forme d'un VOLUME_DISK_EXTENTS structure.

Dans le cas simple où le volume réside sur un seul lecteur physique, le numéro du lecteur physique est disponible dans la rubrique diskExtents.Extents[0].DiskNumber

13 votes

Que se passe-t-il s'il y a un disque vide sans aucun volume (monté) ?

2 votes

Il convient de noter que la mise en œuvre de DeviceIoControl(IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS) échouera si un volume s'étend sur plusieurs disques. En d'autres termes, vous devez d'abord demander DeviceIoControl pour la taille de VOLUME_DISK_EXTENTS puis alloue cette quantité de mémoire, et enfin l'appelle à nouveau avec la mémoire tampon allouée. Cette méthode fonctionne de la manière indiquée ci-dessus parce que la plupart des volumes résident sur un seul disque.

0 votes

Désolé, je ne peux pas ouvrir le fichier " \\.\C :" en utilisant CreateFile((_T(" \\.\C :"), GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,///*FILE_FLAG_WRITE_THROUGH |*/FILE_FLAG_NO_BUFFERING, NULL) ; Pourriez-vous résoudre mon problème ?

39voto

C'est peut-être 5 ans trop tard :). Mais comme je ne vois pas de réponse pour l'instant, j'ajoute ceci.

Nous pouvons utiliser Mise en place des API pour obtenir la liste des disques, c'est-à-dire des périphériques dans le système mettant en œuvre GUID_DEVINTERFACE_DISK .

Une fois que nous disposons des chemins d'accès de leurs appareils, nous pouvons émettre des IOCTL_STORAGE_GET_DEVICE_NUMBER pour construire "\\.\PHYSICALDRIVE%d" avec STORAGE_DEVICE_NUMBER.DeviceNumber

Voir aussi SetupDiGetClassDevs fonction

#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;
}

0 votes

Ajout d'un autre lien (je n'avais pas assez de rep pour le poster dans la réponse) Fonctions de l'API de configuration

1 votes

Cela semble intéressant. Plus complet que ma réponse ci-dessus. +1

0 votes

Noter que ces fonctions de l'interface SetupAPI pas seulement liste tous physique mais aussi des disques virtuels - en fait tous lecteur de disque enregistré interface sera listée, il me semble que cette peut L'utilisation de SetupAPI est beaucoup plus complexe que ce qui est suggéré dans cette réponse.

14voto

Mick Points 7470

J'ai modifié un programme open-source appelé "dskwipe" afin d'en extraire les informations relatives au disque. Dskwipe est écrit en C, et vous pouvez en tirer cette fonction. Le binaire et les sources sont disponibles ici : dskwipe 0.3 est disponible

Les informations renvoyées ressembleront à ceci :

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

1 votes

Je pensais que c'était le cas, mais la recherche brute des lecteurs est forcée N'y a-t-il pas une interface utilisateur qui renvoie simplement les périphériques ?

2 votes

Oui. SetupApi dans Win32, les noms de fonctions commencent par SetupDi.

10voto

Die in Sente Points 5387

GetLogicalDrives() énumère toutes les partitions de disque montées, pas les lecteurs physiques.

Vous pouvez énumérer les lettres de lecteur avec (ou sans) GetLogicalDrives, puis appeler QueryDosDevice() pour savoir à quel lecteur physique la lettre est associée.

Vous pouvez également décoder les informations dans le registre à l'adresse HKEY_LOCAL_MACHINE \SYSTEM\MountedDevices. Le codage des données binaires n'est cependant pas évident. Si vous disposez d'un exemplaire du livre de Russinovich et Solomon, Microsoft Windows Internals, cette ruche de registre est abordée au chapitre 10.

3 votes

QueryDosDevice rétablit la partition, pas le disque lui-même. Un seul disque est divisé en C : et D :, Win7 x64. Donc : c => " \Device\HarddiskVolume2 " ; d => " \Device\HarddiskVolume3 '"

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X