Wie listet man physische Laufwerke auf?

Lesezeit: 10 Minuten

Benutzeravatar von CiNN
CiNN

Wie listet man physische Festplatten in Windows auf? Um eine Liste zu erhalten "\\\\.\PhysicalDrive0" verfügbar.

#WMIC
Wmic ist ein sehr komplettes Werkzeug

wmic diskdrive list

zum Beispiel eine (zu) detaillierte Liste liefern

für weniger Infos

wmic diskdrive list brief 

#C Sebastian Godelet erwähnt in den Kommentaren:

In C:

system("wmic diskdrive list");

Wie kommentiert, können Sie auch die WinAPI aufrufen, aber … wie in “Wie erhalte ich Daten von WMI mit einer C-Anwendung?” gezeigt, ist dies ziemlich komplex (und wird im Allgemeinen mit C++ und nicht mit C ausgeführt).


#PowerShell Oder mit PowerShell:

Get-WmiObject Win32_DiskDrive

Update Feb. 2022, Microsoft kündigt in „Windows 10-Features, die wir nicht mehr entwickeln

Das WMIC-Tool ist in Windows 10, Version 21H1 und der Version 21H1 General Availability Channel von Windows Server veraltet.

Dieses Tool wird ersetzt durch Windows PowerShell für WMI.

Hinweis: Diese Einstellung gilt nur für die Befehlszeilenverwaltungstool. WMI selbst ist nicht betroffen.

  • -1 Beantwortet nicht die Frage, die danach fragt, wie es in C zu tun ist.

    – unixman83

    16. Februar 2012 um 13:26 Uhr

  • +1 Beantwortet die Frage nicht, ist aber eine sehr nützliche Information 🙂

    – Grodriguez

    27. Juli 2012 um 7:53 Uhr

  • du könntest eins machen system("wmic diskdrive list"); in C

    – Sebastian

    21. November 2012 um 13:28 Uhr

  • Sie können WMI auch über WinApi verwenden und nicht nur die wmic-App aufrufen.

    – Alex P.

    22. Januar 2019 um 21:30 Uhr


  • Win32_DiskDrive listet keine physische Festplatte auf, wenn Software-Raid oder StorageSpaces aktiviert sind. Ursprüngliche physische Festplatten wurden herausgefiltert. Einfach mit PowerShell Get-PhysicalDisk zu vergleichen

    – Dmitri Gusarow

    1. März 2020 um 2:07 Uhr


Eine Möglichkeit, dies zu tun:

  1. Logische Laufwerke aufzählen mit GetLogicalDrives

  2. Öffnen Sie für jedes logische Laufwerk eine Datei mit dem Namen "\\.\X:" (ohne die Anführungszeichen), wobei X der logische Laufwerksbuchstabe ist.

  3. Anruf DeviceIoControl Übergeben des Handles an die im vorherigen Schritt geöffnete Datei und die dwIoControlCode Parametersatz auf 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);
    

Dies gibt Informationen über den physischen Standort eines logischen Datenträgers als a VOLUME_DISK_EXTENTS Struktur.

In dem einfachen Fall, in dem sich das Volume auf einem einzelnen physischen Laufwerk befindet, ist die Nummer des physischen Laufwerks in verfügbar diskExtents.Extents[0].DiskNumber

  • Was ist, wenn es eine leere Festplatte ohne (gemountete) Volumes gibt?

    – j_kubik

    7. Juli 2014 um 2:15 Uhr

  • Beachten Sie, dass seine vorgeschlagene Implementierung von DeviceIoControl(IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS) Der Aufruf schlägt fehl, wenn sich ein Volume über mehrere Festplatten erstreckt. Mit anderen Worten, Sie müssen zuerst fragen DeviceIoControl für die Größe von VOLUME_DISK_EXTENTS struct, weisen Sie dann so viel Speicher zu und rufen Sie es erst dann mit dem zugewiesenen Puffer erneut auf. Es funktioniert wie oben gezeigt, da sich die meisten Volumes auf nur einer Festplatte befinden.

    – ahmd0

    24. Oktober 2015 um 21:32 Uhr

  • Entschuldigung, ich kann “\\.\C:” nicht erfolgreich öffnen, indem ich 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); Können Sie mein Problem lösen?

    – Bogenschütze Han

    12. November 2015 um 7:25 Uhr


  • @ahmd0 VOLUME_DISK_EXTENTS enthält genügend Speicher für einen Extent, sodass Sie ihn wie Grodriguez vorschlagen nennen und dann prüfen können success || ERROR_MORE_DATA == GetLastError() da uns sowieso nur der erste Extent interessiert.

    – Millie Smith

    24. März 2017 um 17:17 Uhr

  • Verwenden Sie 0 anstelle von GENERIC_READ, dies ermöglicht das Öffnen der Festplatte auch ohne Administratorrechte, aber Sie können dennoch Metainformationen wie Festplattenerweiterungen lesen.

    – ivan.ukr

    12. Juli 2018 um 14:46 Uhr

aruns Benutzeravatar
arun

Das könnte 5 Jahre zu spät sein :). Aber da ich noch keine Antwort darauf sehe, füge ich dies hinzu.

Wir können benutzen APIs einrichten um die Liste der Festplatten zu erhalten, dh Geräte in der Systemimplementierung GUID_DEVINTERFACE_DISK.

Sobald wir ihre Gerätepfade haben, können wir sie ausgeben IOCTL_STORAGE_GET_DEVICE_NUMBER konstruieren "\\.\PHYSICALDRIVE%d" mit STORAGE_DEVICE_NUMBER.DeviceNumber

Siehe auch SetupDiGetClassDevs Funktion

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

  • Hinzufügen eines weiteren Links (ich hatte nicht genug Repräsentanten, um in der Antwort zu posten) API-Funktionen einrichten

    – arun

    12. August 2013 um 9:19 Uhr


  • Hört sich interessant an. Vollständiger als meine Antwort oben. +1

    – VonC

    12. August 2013 um 10:26 Uhr

  • Beachten Sie, dass diese SetupAPI-Funktionen dies tun nicht nur alle aufzählen körperlich Laufwerke, sondern auch virtuelle – tatsächlich jeder registriertes Laufwerk Schnittstelle aufgelistet werden, denke ich kann Lösung für die Frage sein, aber es werden auch viele “Rauschdaten” erzeugt, die Verwendung von SetupAPI ist viel komplexer als das, was in dieser Antwort vorgeschlagen wird

    – spezialist

    20. April 2015 um 0:06 Uhr


  • Ich schrieb eine kleine Bibliothek namens libwindevblk basierend auf der obigen Antwort, die Laufwerke auflistet, nach Möglichkeit Volume-Namen abruft und eine API bereitstellt, mit der Partitionen einfach gelesen/geschrieben werden können

    – Vinzenz Ricosti

    21. August 2020 um 10:57 Uhr


Die Antwort ist viel einfacher als alle oben genannten Antworten. Die Liste der physischen Laufwerke wird tatsächlich in einem Registrierungsschlüssel gespeichert, der auch die Gerätezuordnung bereitstellt.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\disk\Enum

Zählen ist die Nummer von PhysicalDrive# und jeder nummerierte Registrierungswert ist das entsprechende physische Laufwerk.

Beispielsweise ist der Registrierungswert “0” PhysicalDrive0. Der Wert ist das tatsächliche Gerät, dem PhysicalDrive0 zugeordnet ist. Der hier enthaltene Wert kann übergeben werden CM_Locate_DevNode innerhalb des Parameters pDeviceID um die Plug-and-Play-Dienste zu nutzen. Auf diese Weise können Sie eine Fülle von Informationen über das Gerät sammeln. Beispielsweise die Eigenschaften des Geräte-Managers wie “Friendly Display Name”, wenn Sie einen Namen für das Laufwerk benötigen, Seriennummern und mehr.

WMI-Dienste, die möglicherweise nicht auf dem System ausgeführt werden, oder andere Hacker sind nicht erforderlich, und diese Funktionalität ist in Windows seit mindestens 2000 vorhanden und ist in Windows 10 weiterhin der Fall.

Ich habe ein Open-Source-Programm namens “dskwipe” modifiziert, um diese Festplatteninformationen daraus zu ziehen. Dskwipe ist in C geschrieben, und Sie können diese Funktion daraus ziehen. Die Binärdatei und die Quelle sind hier verfügbar: dskwipe 0.3 wurde veröffentlicht

Die zurückgegebenen Informationen sehen in etwa so aus:

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

  • Ich dachte, es wäre es, aber es erzwingt eine Brute-Suche nach den Laufwerken. Gibt es nicht eine API, die nur die Geräte zurückmeldet?

    – CiNN

    9. Dezember 2008 um 23:03 Uhr

  • Ja. SetupApi in Win32, Funktionsnamen beginnen mit SetupDi

    – Warren P

    16. Dezember 2011 um 20:06 Uhr

Die einzig richtige Antwort ist die von @Grodriguez, und hier ist ein Code, den zu schreiben er zu faul war:

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

Ich denke, dass die Installation des Windows Driver Development Kit ein ziemlich langwieriger Prozess ist, daher habe ich die Deklarationen beigefügt, die man verwenden muss DeviceIoControl für diese Aufgabe.

  • Ich dachte, es wäre es, aber es erzwingt eine Brute-Suche nach den Laufwerken. Gibt es nicht eine API, die nur die Geräte zurückmeldet?

    – CiNN

    9. Dezember 2008 um 23:03 Uhr

  • Ja. SetupApi in Win32, Funktionsnamen beginnen mit SetupDi

    – Warren P

    16. Dezember 2011 um 20:06 Uhr

Stirb in Sentes Benutzer-Avatar
Sterben in Sente

GetLogicalDrives() listet alle gemounteten Festplattenpartitionen auf, nicht physische Laufwerke.

Sie können die Laufwerksbuchstaben mit (oder ohne) GetLogicalDrives aufzählen und dann QueryDosDevice() aufrufen, um herauszufinden, welchem ​​physischen Laufwerk der Buchstabe zugeordnet ist.

Alternativ können Sie die Informationen in der Registrierung unter HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices entschlüsseln. Die dortigen binären Datenkodierungen sind jedoch nicht offensichtlich. Wenn Sie eine Kopie des Buches Microsoft Windows Internals von Russinovich und Solomon haben, wird dieser Registrierungsbaum in Kapitel 10 besprochen.

  • QueryDosDevice gibt die Partition zurück, nicht die Festplatte selbst. Eine einzelne Festplatte wird auf C: und D: aufgeteilt, Win7 x64. Also: c => “\Device\HarddiskVolume2”; d => “\Gerät\HarddiskVolume3′”

    – Arioch ‘Die

    25. Juli 2012 um 12:47 Uhr

1419560cookie-checkWie listet man physische Laufwerke auf?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy