Wie liste ich physische Festplatten in Windows auf? Um eine Liste der "\\\\.\PhysicalDrive0"
verfügbaren zu erhalten.
c
windows
winapi
hard-drive
CiNN
quelle
quelle
system("wmic diskdrive list");
in CEin Weg, es zu tun:
Zählen Sie logische Laufwerke mit auf
GetLogicalDrives
Öffnen Sie für jedes logische Laufwerk eine Datei mit dem Namen
"\\.\X:"
(ohne Anführungszeichen), wobei X der Buchstabe des logischen Laufwerks ist.Rufen Sie auf,
DeviceIoControl
indem Sie das Handle an die im vorherigen Schritt geöffnete Datei übergeben und dendwIoControlCode
Parameter auf Folgendes setzenIOCTL_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 Speicherort eines logischen Volumes als
VOLUME_DISK_EXTENTS
Struktur zurück.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
quelle
DeviceIoControl(IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS)
Aufrufs fehlschlägt, wenn sich ein Volume über mehrere Festplatten erstreckt. Mit anderen Worten, Sie müssen zuerst nachDeviceIoControl
der Größe derVOLUME_DISK_EXTENTS
Struktur fragen , dann so viel Speicher zuweisen und erst dann mit dem zugewiesenen Puffer erneut aufrufen. Dies funktioniert wie oben gezeigt, da sich die meisten Volumes auf nur einer Festplatte befinden.VOLUME_DISK_EXTENTS
enthält genügend Speicher für eine Ausdehnung, sodass Sie es so aufrufen können, wie es Grodriguez vorschlägt, und dann nachsehen können,success || ERROR_MORE_DATA == GetLastError()
da wir uns sowieso nur um die erste Ausdehnung kümmern.Dies könnte 5 Jahre zu spät sein :). Aber da ich noch keine Antwort darauf sehe, füge ich dies hinzu.
Wir können Setup-APIs verwenden , um die Liste der Festplatten abzurufen, dh der Geräte im System, die implementiert werden
GUID_DEVINTERFACE_DISK
.Sobald wir ihre Gerätepfade haben, können wir ausgeben
IOCTL_STORAGE_GET_DEVICE_NUMBER
zu konstruieren ,"\\.\PHYSICALDRIVE%d"
mitSTORAGE_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; }
quelle
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 enthält.
HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services \ disk \ Enum
Count ist die Anzahl der PhysicalDrive # und jeder nummerierte Registrierungswert ist das entsprechende physische Laufwerk.
Der Registrierungswert "0" ist beispielsweise PhysicalDrive0. Der Wert ist das tatsächliche Gerät, dem PhysicalDrive0 zugeordnet ist. Der hier enthaltene Wert kann in geben wird CM_Locate_DevNode innerhalb Parameter pDeviceID die Plug - and - Play - Dienste zu nutzen. Auf diese Weise können Sie eine Fülle von Informationen auf dem Gerät sammeln. B. die Eigenschaften des Geräte-Managers wie "Benutzerfreundlicher Anzeigename", wenn Sie einen Namen für das Laufwerk, Seriennummern und mehr benötigen.
Es sind keine WMI-Dienste erforderlich, die möglicherweise nicht auf dem System oder einem anderen Hacker ausgeführt werden. Diese Funktionalität ist in Windows seit mindestens 2000 vorhanden und ist in Windows 10 weiterhin der Fall.
quelle
Ich habe ein Open-Source-Programm namens "dskwipe" geändert, 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 ungefähr 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
quelle
Der einzig sichere Weg, dies zu tun, ist anzurufen
CreateFile()
alle bei\\.\Physicaldiskx
denen x zwischen 0 und 15 liegt (16 ist die maximal zulässige Anzahl von Festplatten). Überprüfen Sie den zurückgegebenen Handle-Wert. Wenn ungültig,GetLastError()
auf ERROR_FILE_NOT_FOUND prüfen . Wenn etwas anderes zurückgegeben wird, ist die Festplatte vorhanden, Sie können jedoch aus irgendeinem Grund nicht darauf zugreifen.quelle
15
? Zählen Sie weiter, bis Sie versagen. Ich bin nicht sicher, ob eine Gerätenummer vom Betriebssystem übersprungen wird.Die einzig richtige Antwort ist die von @Grodriguez, und hier ist ein Code, den er zu faul war, um ihn zu schreiben:
#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
DeviceIoControl
für diese Aufgabe verwendet werden müssen.quelle
DeviceIoControl
falsch an. Sie können nicht davon ausgehen, dass es nur einen Umfang gibt. Sie müssen nachDeviceIoControl
der Größe des benötigtenVOLUME_DISK_EXTENTS
Puffers fragen .DeviceIoControl
im Grunde den Speicher für eine Single auf,VOLUME_DISK_EXTENTS
wie Sie es getan haben, prüfen dann aber, ob sie fehlgeschlagen ist, und prüfen, ob sie zurückgegeben wurde Weisen SieERROR_MORE_DATA
inGetLastError
und wenn ja, einen neuen Puffer für dieNumberOfDiskExtents
Anzahl der zurückgegebenenDISK_EXTENT
Strukturen zu, rufen Sie ihnDeviceIoControl
erneut auf und stellen Sie sicher, dass er erfolgreich ist. Sie tun dies offensichtlich nicht, wenn der erste AnrufDeviceIoControl
erfolgreich ist.GetLogicalDrives () listet alle gemounteten Festplattenpartitionen auf, keine physischen Laufwerke.
Sie können die Laufwerksbuchstaben mit (oder ohne) GetLogicalDrives auflisten 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 dekodieren. Die dortigen binären Datencodierungen sind jedoch nicht offensichtlich. Wenn Sie eine Kopie von Russinovichs und Solomons Buch Microsoft Windows Internals haben, wird diese Registrierungsstruktur in Kapitel 10 erläutert.
quelle
Diese WMIC-Befehlskombination funktioniert einwandfrei:
wmic volume list brief
quelle
Vielleicht möchten Sie die alten A: - und B: -Laufwerke einbeziehen, da Sie nie wissen, wer sie möglicherweise verwendet! Ich habe es satt, dass USB-Laufwerke meine beiden SDHC-Laufwerke, die nur für Readyboost bestimmt sind, anstoßen. Ich habe sie hohen Buchstaben Z: Y: mit einem Dienstprogramm zugewiesen, das Geräten Laufwerksbuchstaben nach Ihren Wünschen zuweist. Ich habe mich gefragt ... Kann ich einen Readyboost-Laufwerksbuchstaben A: erstellen? JA! Kann ich meinen zweiten SDHC-Laufwerksbuchstaben als B: eingeben? JA!
Ich habe früher Floppy Drives verwendet und hätte nie gedacht, dass A: oder B: für Readyboost nützlich sein würden.
Mein Punkt ist, nehmen Sie nicht an, dass A: & B: von niemandem für irgendetwas verwendet wird. Vielleicht finden Sie sogar den alten SUBST-Befehl, der verwendet wird!
quelle
Ich bin heute in meinem RSS-Reader darauf gestoßen. Ich habe eine sauberere Lösung für Sie. Dieses Beispiel befindet sich in Delphi, kann jedoch sehr einfach in C / C ++ konvertiert werden (es ist alles Win32).
Fragen Sie alle Wertnamen vom folgenden Registrierungsspeicherort ab: HKLM \ SYSTEM \ MountedDevices
Übergeben Sie sie nacheinander an die folgende Funktion, und Sie erhalten den Gerätenamen zurück. Ziemlich sauber und einfach! Ich habe diesen Code in einem Blog hier gefunden.
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;
quelle
Wenn Sie "physischen" Zugriff wünschen, entwickeln wir diese API, mit der Sie eventuell mit Speichergeräten kommunizieren können. Es ist Open Source und Sie können den aktuellen Code für einige Informationen sehen. Weitere Funktionen finden Sie unter: https://github.com/virtium/vtStor
quelle
Hier ist eine neue Lösung für WMI-Aufrufe.
Dann müssen Sie nur noch anrufen:
queryAndPrintResult(L"SELECT * FROM Win32_DiskDrive", L"Name");
quelle
Erstellen Sie eine Liste aller Buchstaben im englischen US-Alphabet und überspringen Sie a & b. "CDEFGHIJKLMNOPQRSTUVWXYZ". Öffnen Sie jedes dieser Laufwerke mit
CreateFile
zCreateFile("\\.\C:")
. Wenn es nicht zurückkehrt, habenINVALID_HANDLE_VALUE
Sie ein "gutes" Laufwerk. Nehmen Sie als nächstes dieses Handle und führen Sie es durchDeviceIoControl
, um die Disk # zu erhalten. Siehe meine verwandte Antwort für weitere Details .quelle