it-swarm.dev

¿Cómo listar los discos físicos?

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

67
CiNN

WMIC

wmic es una herramienta muy completa

wmic diskdrive list

proporcionar una (demasiado) lista detallada, por ejemplo

por menos información

wmic diskdrive list brief 

Do

Sebastian Godelet menciones en los comentarios :

Cía:

system("wmic diskdrive list");

Como comenté, también puede llamar a WinAPI, pero ... como se muestra en " ¿Cómo obtener datos de WMI usando una aplicación C? ", esto es bastante complejo (y generalmente se hace con C++, no C).

Potencia Shell

O con PowerShell:

Get-WmiObject Win32_DiskDrive
61
VonC

Una forma de hacerlo:

  1. Enumerar unidades lógicas utilizando 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 identificador al archivo abierto en el paso anterior, y el parámetro dwIoControlCode se establece en 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 en que el volumen reside en una sola unidad física, el número de unidad física está disponible en diskExtents.Extents[0].DiskNumber

40
Grodriguez

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

Podemos usar Configurar API para obtener la lista de discos, es decir, dispositivos en el sistema que implementa GUID_DEVINTERFACE_DISK .

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

Ver también la función 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;
}
27
arun

La respuesta es mucho más simple que todas las respuestas anteriores. La lista de unidades físicas se almacena realmente en una clave de 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 la unidad física correspondiente.

Por ejemplo, el valor de registro "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 en el parámetro pDeviceID para usar los servicios plug and play. Esto le permitirá recopilar una gran cantidad de información en el dispositivo. Tales como las propiedades del Administrador de dispositivos como "Nombre para mostrar amigable" si necesita un nombre para la unidad, números de serie y más.

No hay necesidad de servicios WMI que no se estén ejecutando en el sistema u otra piratería, y esta funcionalidad ha estado presente en Windows desde al menos 2000 y sigue siendo el caso en Windows 10.

13
HooliganCoder

He modificado un programa de código abierto llamado "dskwipe" para extraer esta información del disco. Dskwipe está escrito en C, y puede sacar esta función de él. El binario y la fuente están disponibles aquí: Se ha lanzado dskwipe 0.3

La información devuelta se verá así:

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
12
Mick

La única manera segura de hacer esto es llamar a CreateFile() en todos los \\.\Physicaldiskx donde x es de 0 a 15 (16 es el número máximo de discos permitido). Compruebe el valor de identificador devuelto. Si no es válido, marque GetLastError() para ERROR_FILE_NOT_FOUND . Si devuelve algo más, entonces el disco existe pero no puede acceder a él por alguna razón.

9
anni

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

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

Creo que la instalación del Kit de desarrollo de controladores de Windows es un proceso bastante largo, por lo que he incluido las declaraciones que uno necesita usar DeviceIoControl para esta tarea.

8
polkovnikov.ph

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

Puede enumerar las letras de unidad con (o sin) GetLogicalDrives, luego llamar a QueryDosDevice () para averiguar a qué unidad física está asignada 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 Microsoft Windows Internals de Russinovich y Solomon, esta sección de registro se trata en el Capítulo 10.

8
Die in Sente

La combinación de comandos Thic WMIC funciona bien:

wmic volume list brief
2
user2506992

¡Es posible que desee incluir las unidades antiguas A: y B: como nunca se sabe quién puede usarlas! Me cansé de que las unidades USB golpearan 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 desee. Me pregunté ... ¿Puedo hacer una letra de unidad Readyboost A:? ¡SÍ! ¿Puedo poner mi segunda letra de unidad SDHC como B:? ¡SÍ!

He usado las unidades de disquete en el pasado, nunca pensé que A: o B: serían útiles para Readyboost.

Lo que quiero decir es que no asuma que A: & B: no será utilizado por nadie para nada. ¡Puede incluso encontrar el antiguo comando SUBST que se está utilizando!

2
liverwort

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

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

Uno por uno, 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;
1
Mick

Aquí es una solución nueva de hacerlo con llamadas WMI.
Entonces, todo lo que necesitas hacer es simplemente llamar:

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

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

1
phandinhlan