Comment lister les disques physiques sous Windows? Pour obtenir une liste de "\\\\.\PhysicalDrive0"
disponible.
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
Sebastian Godelet mentionne dans les commentaires :
En C:
system("wmic diskdrive list");
Comme indiqué, vous pouvez également appeler WinAPI, mais ... comme indiqué dans " Comment obtenir des données à partir de WMI à l'aide d'une application C? ", ceci est assez complexe C).
Ou avec PowerShell:
Get-WmiObject Win32_DiskDrive
Une façon de le faire:
Énumérer les lecteurs logiques à l'aide de GetLogicalDrives
Pour chaque lecteur logique, ouvrez un fichier nommé "\\.\X:"
(sans les guillemets) où X est la lettre du lecteur logique.
Appelez DeviceIoControl
en transmettant le descripteur au fichier ouvert à l'étape précédente et définissez le paramètre dwIoControlCode
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);
Ceci retourne des informations sur l'emplacement physique d'un volume logique, sous la forme 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 diskExtents.Extents[0].DiskNumber
Cela pourrait être 5 ans trop tard :). Mais comme je ne vois pas encore de réponse à cela, ajoutez ceci.
Nous pouvons utiliser Setup APIs pour obtenir la liste des disques, c’est-à-dire les périphériques du système implémentant GUID_DEVINTERFACE_DISK
.
Une fois que nous avons leurs chemins de périphérique, nous pouvons émettre IOCTL_STORAGE_GET_DEVICE_NUMBER
pour construire "\\.\PHYSICALDRIVE%d"
avec STORAGE_DEVICE_NUMBER.DeviceNumber
Voir aussi SetupDiGetClassDevs
function
#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;
}
La réponse est beaucoup plus simple que toutes les réponses ci-dessus. La liste des lecteurs physiques est en réalité stockée dans une clé de registre qui donne également le mappage du périphérique.
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\disk\Enum
Count est le nombre de disques PhysicalDrive # et chaque valeur de registre numérotée est le lecteur physique correspondant.
Par exemple, la valeur de registre "0" correspond à PhysicalDrive0. La valeur correspond au périphérique réel mappé sur PhysicalDrive0. La valeur contenue ici peut être passée dans CM_Locate_DevNode dans le paramètre pDeviceID pour utiliser les services plug-and-play. Cela vous permettra de recueillir une mine d'informations sur l'appareil. Telles que les propriétés du Gestionnaire de périphériques telles que "Nom d'affichage convivial" si vous avez besoin d'un nom pour le lecteur, de numéros de série, etc.
Il n’est pas nécessaire de recourir à des services WMI qui ne s'exécutent peut-être pas sur le système ou d’autres types de piratage. Cette fonctionnalité est présente dans Windows depuis au moins 2000 et continue de l’être dans Windows 10.
J'ai modifié un programme open-source appelé "dskwipe" afin d'extraire cette information de disque. Dskwipe est écrit en C et vous pouvez en extraire cette fonction. Le binaire et le source sont disponibles ici: dskwipe 0.3 a été publié
Les informations retourné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
Le seul moyen sûr de procéder consiste à appeler CreateFile()
sur tout \\.\Physicaldiskx
Où x est compris entre 0 et 15 (16 correspond au nombre maximal de disques autorisé). Vérifiez la valeur de la poignée renvoyée. Si non valide, vérifiez GetLastError()
pour ERROR_FILE_NOT_FOUND. S'il renvoie autre chose, le disque existe mais vous ne pouvez pas y accéder pour une raison quelconque.
La seule réponse correcte est celle de @Grodriguez, et voici un code qu'il était trop paresseux pour écrire:
#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;
}
}
Je pense que l'installation du kit de développement de pilotes Windows est un processus assez long. J'ai donc inclus les déclarations nécessaires pour utiliser DeviceIoControl
dans cette tâche.
GetLogicalDrives () énumère toutes les partitions de disque montées, pas lecteurs physiques.
Vous pouvez énumérer les lettres de lecteur avec (ou sans) GetLogicalDrives, puis appeler QueryDosDevice () pour déterminer le lecteur physique auquel la lettre est mappée.
Vous pouvez également décoder les informations du registre à l'adresse HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices. Les codages de données binaires ne sont toutefois pas évidents. Si vous avez un exemplaire du livre Microsoft Windows Internals de Russinovich et Solomon, ce registre Hive est présenté au chapitre 10.
La combinaison de commandes Thic WMIC fonctionne bien:
wmic volume list brief
Vous voudrez peut-être inclure les anciens disques A: et B: car vous ne savez jamais qui les utilise! J'en avais marre des clés USB qui heurtaient mes deux disques SDHC réservés à Readyboost. Je les avais assignées aux lettres majuscules Z: Y: avec un utilitaire qui assignera les lettres de lecteur aux périphériques à votre guise. Je me demandais…. Puis-je créer une lettre de lecteur Readyboost A:? OUI! Puis-je mettre ma deuxième lettre de lecteur SDHC comme B:? OUI!
J'ai utilisé des lecteurs de disquettes dans la journée, jamais pensé que A: ou B: serait utile pour Readyboost.
Mon point est, ne supposez pas que A: & B: ne sera utilisé par personne pour quoi que ce soit. Vous pourriez même trouver l'ancienne commande SUBST utilisée!
Je viens de découvrir cela dans mon lecteur RSS aujourd'hui. J'ai une solution plus propre pour vous. Cet exemple est en Delphi, mais peut très facilement être converti en C/C++ (c'est tout Win32).
Interrogez tous les noms de valeur à partir de l'emplacement de registre suivant: HKLM\SYSTEM\MountedDevices
Un par un, transmettez-les à la fonction suivante et vous recevrez le nom du périphérique. Assez propre et simple! J'ai trouvé ce code sur un blog ici.
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;
Ici est une nouvelle solution en faisant des appels WMI.
Ensuite, tout ce que vous avez à faire est simplement d'appeler:
queryAndPrintResult(L"SELECT * FROM Win32_DiskDrive", L"Name");
Si vous souhaitez un accès "physique", nous développons cette API qui vous permettra éventuellement de communiquer avec des périphériques de stockage. C'est open source et vous pouvez voir le code actuel pour quelques informations. Revenez pour plus de fonctionnalités: https://github.com/virtium/vtStor