如何在Windows中列出物理磁盘?为了获得"\\\\.\PhysicalDrive0"
可用的列表.
wmic是一个非常完整的工具
wmic diskdrive list
例如,提供(太多)详细列表
少知情
wmic diskdrive list brief
C
Sebastian Godelet 在评论中提到:
在C:
system("wmic diskdrive list");
如评论所述,您也可以调用WinAPI,但是......如" 如何使用C应用程序从WMI获取数据? "中所示,这非常复杂(通常使用C++,而不是C).
电源外壳或者使用PowerShell:
Get-WmiObject Win32_DiskDrive
一种方法:
使用枚举逻辑驱动器 GetLogicalDrives
对于每个逻辑驱动器,打开一个名为"\\.\X:"
(不带引号)的文件,其中X是逻辑驱动器号.
调用DeviceIoControl
将句柄传递给上一步打开的文件,dwIoControlCode
参数设置为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);
这将返回逻辑卷的物理位置信息,作为VOLUME_DISK_EXTENTS
结构.
在卷位于单个物理驱动器上的简单情况下,可以使用物理驱动器号 diskExtents.Extents[0].DiskNumber
这可能是5年太晚了:).但是,由于我还没有找到答案,所以加上这个.
我们可以使用Setup API来获取磁盘列表,即系统实现中的设备GUID_DEVINTERFACE_DISK
.
一旦我们有了自己的设备路径,我们可以发出IOCTL_STORAGE_GET_DEVICE_NUMBER
来构建"\\.\PHYSICALDRIVE%d"
与STORAGE_DEVICE_NUMBER.DeviceNumber
另见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; }
答案远比上述所有答案都简单.物理驱动器列表实际上存储在注册表项中,该注册表项还提供设备映射.
HKEY_LOCAL_MACHINE \系统\ CurrentControlSet \服务\硬盘\枚举
Count是PhysicalDrive#的编号,每个编号的Registry Value是相应的物理驱动器.
例如,注册表值"0"是PhysicalDrive0.该值是PhysicalDrive0映射到的实际设备.此处包含的值可以传递到CM_Locate_DevNode参数中pDeviceID使用即插即用服务.这样您就可以在设备上收集大量信息.例如,如果您需要驱动器名称,序列号等,请使用设备管理器中的属性,如"友好显示名称".
不需要在系统或其他hackery上运行的WMI服务,并且至少在2000年以来Windows中一直存在此功能,并且在Windows 10中仍然如此.
我修改了一个名为"dskwipe"的开源程序,以便从中获取此磁盘信息.Dskwipe是用C语言编写的,你可以将它从中拉出来.二进制和源代码可在此处获得:dskwipe 0.3已发布
返回的信息将如下所示:
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
唯一确定的方法是调用x从0到15的CreateFile()
所有\\.\Physicaldiskx
位置(16是允许的最大磁盘数).检查返回的句柄值.如果作废的支票GetLastError()
为ERROR_FILE_NOT_FOUND.如果它返回任何其他内容,则磁盘存在,但由于某种原因您无法访问它.
GetLogicalDrives()枚举所有已安装的磁盘分区,而不是物理驱动器.
您可以使用(或不使用)GetLogicalDrives枚举驱动器号,然后调用QueryDosDevice()以找出该字母映射到的物理驱动器.
或者,您可以在HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices中解码注册表中的信息.然而,那里的二进制数据编码并不明显.如果您有一份Russinovich和Solomon的书Microsoft Windows Internals,那么这个注册表配置单元将在第10章中讨论.
唯一正确的答案是@Grodriguez,这是一个他懒得写的代码:
#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; } }
我认为安装Windows驱动程序开发工具包是一个漫长的过程,所以我已经包含了需要DeviceIoControl
用于此任务的声明.