当前位置:  开发笔记 > 编程语言 > 正文

如何列出物理磁盘?

如何解决《如何列出物理磁盘?》经验,为你挑选了8个好方法。

如何在Windows中列出物理磁盘?为了获得"\\\\.\PhysicalDrive0"可用的列表.



1> VonC..:
WMIC

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


+1不回答问题,但它是一个非常有用的信息:-)
-1不回答问题,这是在C中询问如何做到这一点.
你可以做一个`系统("wmic diskdrive list");`在C中

2> Grodriguez..:

一种方法:

    使用枚举逻辑驱动器 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


如果没有任何(已安装)卷的空磁盘怎么办?
请注意,如果卷跨越多个磁盘,则建议的"DeviceIoControl(IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS)"调用的实现将失败.换句话说,首先需要向`DeviceIoControl`询问`VOLUME_DISK_EXTENTS`结构的大小,然后分配那么多内存,然后再用分配的缓冲区再次调用它.它的工作方式如上所示,因为大多数卷只驻留在一个磁盘上.

3> 小智..:

这可能是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;
}



4> 小智..:

答案远比上述所有答案都简单.物理驱动器列表实际上存储在注册表项中,该注册表项还提供设备映射.

HKEY_LOCAL_MACHINE \系统\ CurrentControlSet \服务\硬盘\枚举

Count是PhysicalDrive#的编号,每个编号的Registry Value是相应的物理驱动器.

例如,注册表值"0"是PhysicalDrive0.该值是PhysicalDrive0映射到的实际设备.此处包含的值可以传递到CM_Locate_DevNode参数中pDeviceID使用即插即用服务.这样您就可以在设备上收集大量信息.例如,如果您需要驱动器名称,序列号等,请使用设备管理器中的属性,如"友好显示名称".

不需要在系统或其他hackery上运行的WMI服务,并且至少在2000年以来Windows中一直存在此功能,并且在Windows 10中仍然如此.



5> Mick..:

我修改了一个名为"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


是.Win32中的SetupApi,函数名称以SetupDi开头

6> 小智..:

唯一确定的方法是调用x从0到15的CreateFile()所有\\.\Physicaldiskx位置(16是允许的最大磁盘数).检查返回的句柄值.如果作废的支票GetLastError()ERROR_FILE_NOT_FOUND.如果它返回任何其他内容,则磁盘存在,但由于某种原因您无法访问它.


你有这个号码的地方?

7> Die in Sente..:

GetLogicalDrives()枚举所有已安装的磁盘分区,而不是物理驱动器.

您可以使用(或不使用)GetLogicalDrives枚举驱动器号,然后调用QueryDosDevice()以找出该字母映射到的物理驱动器.

或者,您可以在HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices中解码注册表中的信息.然而,那里的二进制数据编码并不明显.如果您有一份Russinovich和Solomon的书Microsoft Windows Internals,那么这个注册表配置单元将在第10章中讨论.



8> polkovnikov...:

唯一正确的答案是@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用于此任务的声明.

推荐阅读
谢谢巷议
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有