¿Cómo hacer una lista de discos físicos?

¿Cómo hacer una lista de discos físicos en Windows? Para obtener una lista de "\\\\.\PhysicalDrive0" disponible.

WMIC

wmic es una herramienta muy completa

 wmic diskdrive list 

proporcionar una (demasiado) lista detallada, por ejemplo

para menos información

 wmic diskdrive list brief 

do

Sebastian Godelet menciona en los comentarios :

Cª:

 system("wmic diskdrive list"); 

Potencia Shell

O con PowerShell:

 Get-WmiObject Win32_DiskDrive 

Una forma de hacerlo:

  1. GetLogicalDrives unidades lógicas con GetLogicalDrives

  2. Para cada unidad lógica, abra un archivo llamado "\\.\X:" (sin las comillas) donde X es la letra de la unidad lógica.

  3. Llame a DeviceIoControl pasando el manejador al archivo abierto en el paso anterior, y el parámetro dwIoControlCode configurado a 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); 

Esto devuelve información de la ubicación física de un volumen lógico, como una estructura VOLUME_DISK_EXTENTS .

En el caso simple donde el volumen reside en una sola unidad física, el número de unidad física está disponible en diskExtents.Extents[0].DiskNumber

Esto podría ser 5 años demasiado tarde :). Pero como todavía no veo respuesta para esto, agrego esto.

Podemos usar las API de configuración para obtener la lista de discos, es decir, dispositivos en el sistema que implementan GUID_DEVINTERFACE_DISK .

Una vez que tenemos sus rutas de dispositivo, podemos emitir IOCTL_STORAGE_GET_DEVICE_NUMBER para construir "\\.\PHYSICALDRIVE%d" con STORAGE_DEVICE_NUMBER.DeviceNumber

Ver también la función SetupDiGetClassDevs

 #include  #include  #include  #pragma comment( lib, "setupapi.lib" ) #include  #include  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; } 

Modifiqué un progtwig de código abierto llamado “dskwipe” para extraer la información de este disco. Dskwipe está escrito en C, y puedes sacar esta función de él. El código binario y la fuente están disponibles aquí: dskwipe 0.3 ha sido liberado

La información devuelta tendrá el siguiente aspecto:

 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 

La respuesta es mucho más simple que todas las respuestas anteriores. La lista de unidades físicas se almacena en realidad en una clave del Registro que también proporciona la asignación del dispositivo.

HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services \ disk \ Enum

Count es el número de PhysicalDrive # y cada valor de registro numerado es el disco físico correspondiente.

Por ejemplo, Registry Value “0” es PhysicalDrive0. El valor es el dispositivo real al que se asigna PhysicalDrive0. El valor contenido aquí se puede pasar a CM_Locate_DevNode dentro del parámetro pDeviceID para usar los servicios Plug and Play. Esto le permitirá reunir una gran cantidad de información en el dispositivo. Tales como las propiedades de Device Manager como “Friendly Display Name” si necesita un nombre para la unidad, números de serie y más.

No hay necesidad de servicios WMI que pueden no estar ejecutándose en el sistema u otro hackeo y esta funcionalidad ha estado presente en Windows desde al menos 2000 y continúa siendo el caso en Windows 10.

La única forma segura de hacerlo es llamar a CreateFile() en todo \\.\Physicaldiskx donde x es de 0 a 15 (16 es la cantidad máxima de discos permitidos). Verifique el valor del mango devuelto. Si no es válido, compruebe GetLastError() para ERROR_FILE_NOT_FOUND . Si devuelve algo más, entonces el disco existe pero no puede acceder a él por algún motivo.

GetLogicalDrives () enumera todas las particiones de disco montadas, no las unidades físicas.

Puede enumerar las letras de unidad con (o sin) GetLogicalDrives y luego llamar a QueryDosDevice () para averiguar a qué unidad física se asigna la letra.

Alternativamente, puede decodificar la información en el registro en HKEY_LOCAL_MACHINE \ SYSTEM \ MountedDevices. Sin embargo, las codificaciones de datos binarios no son obvias. Si tiene una copia del libro de Russinovich y Solomon, Microsoft Windows Internals, esta sección de registro se trata en el Capítulo 10.

La única respuesta correcta es la de @Grodriguez, y aquí hay un código que era demasiado perezoso para escribir:

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

Creo que la instalación del Windows Driver Development Kit es un proceso bastante largo, así que he incluido las declaraciones que uno necesita para usar DeviceIoControl para esta tarea.

La combinación de comandos Thic WMIC funciona bien:

 wmic volume list brief 

Puede que quiera incluir las viejas unidades A: y B: ¡ya que nunca se sabe quién podría estar usándolas! Me cansé de las unidades USB que golpean mis dos unidades SDHC que son solo para Readyboost. Los había asignado a Letras altas Z: Y: con una utilidad que asignará letras de unidad a los dispositivos como lo desee. Me preguntaba … ¿Puedo hacer una letra de unidad de Readyboost A:? ¡SÍ! ¿Puedo poner mi segunda letra de unidad SDHC como B:? ¡SÍ!

He usado discos flexibles en el día, nunca pensé que A: o B: serían útiles para Readyboost.

Lo que quiero decir es que no asums que A: & B: no será utilizado por nadie para nada. ¡Incluso podrías encontrar el antiguo comando SUBST en uso!

Acabo de encontrar esto en mi lector RSS hoy. Tengo una solución más limpia para ti. Este ejemplo está en Delphi, pero se puede convertir fácilmente a C / C ++ (todo es Win32).

Consultar todos los nombres de valores de la siguiente ubicación de registro: HKLM \ SYSTEM \ MountedDevices

Una por una, páselos a la siguiente función y se le devolverá el nombre del dispositivo. ¡Bastante limpio y simple! Encontré este código en un blog aquí.

 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; 

Si desea acceso “físico”, estamos desarrollando esta API que eventualmente le permitirá comunicarse con dispositivos de almacenamiento. Es de código abierto y puedes ver el código actual para obtener información. Vuelve para más funciones: https://github.com/virtium/vtStor

Aquí hay una nueva solución para hacerlo al hacer llamadas WMI.
Entonces, todo lo que tienes que hacer es simplemente llamar:

 queryAndPrintResult(L"SELECT * FROM Win32_DiskDrive", L"Name"); 

Haga una lista de todas las letras en el alfabeto inglés de EE. UU., Omitiendo a & b. “CDEFGHIJKLMNOPQRSTUVWXYZ”. Abra cada una de esas unidades con CreateFile por ejemplo CreateFile("\\.\C:") . Si no devuelve INVALID_HANDLE_VALUE , obtendrá un “buen” disco. A continuación, tome ese control y ejecútelo a través de DeviceIoControl para obtener el número de disco. Ver mi respuesta relacionada para más detalles .