web-dev-qa-db-ja.com

物理ディスクを一覧表示する方法は?

Windowsで物理ディスクを一覧表示する方法は? "\\\\.\PhysicalDrive0"のリストを取得するために利用可能。

69
CiNN

WMIC

wmic は非常に完全なツールです

wmic diskdrive list

たとえば、(多すぎる)詳細なリストを提供する

少ない情報で

wmic diskdrive list brief 

C

セバスチャン・ゴデレット 言及 コメント内

Cで:

system("wmic diskdrive list");

コメントしたように、WinAPIを呼び出すこともできますが、...「 Cアプリケーションを使用してWMIからデータを取得する方法? 」に示すように、これは非常に複雑です(一般的にC++ではなく、 C)。

パワーシェル

またはPowerShellで:

Get-WmiObject Win32_DiskDrive
64
VonC

それを行う1つの方法:

  1. GetLogicalDrives を使用して論理ドライブを列挙する

  2. 論理ドライブごとに、"\\.\X:"(引用符なし)という名前のファイルを開きます。Xは論理ドライブ文字です。

  3. 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で利用可能です

43
Grodriguez

これは5年遅すぎるかもしれません:)。しかし、これに対する答えがまだないようで、これを追加します。

Setup APIs を使用して、ディスクのリスト、つまり GUID_DEVINTERFACE_DISK を実装するシステム内のデバイスを取得できます。

デバイスパスを取得したら、 IOCTL_STORAGE_GET_DEVICE_NUMBER を発行して、"\\.\PHYSICALDRIVE%d"STORAGE_DEVICE_NUMBER.DeviceNumberを構築できます。

SetupDiGetClassDevs function も参照してください

#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

答えは上記のすべての答えよりもはるかに簡単です。物理ドライブのリストは実際にはレジストリキーに保存され、デバイスマッピングも提供します。

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\disk\Enum

CountはPhysicalDrive#の数であり、各レジ​​ストリ値は対応する物理ドライブです。

たとえば、レジ​​ストリ値「0」はPhysicalDrive0です。値は、PhysicalDrive0がマップされる実際のデバイスです。ここに含まれる値は、パラメーター内の CM_Locate_DevNodepDeviceIDに渡して、プラグアンドプレイサービスを使用できます。これにより、デバイスに関する豊富な情報を収集できます。ドライブ、シリアル番号などの名前が必要な場合は、「フレンドリ表示名」などのデバイスマネージャーのプロパティなど。

システムまたはその他のハッカーで実行されていない可能性のあるWMIサービスは不要です。この機能は、少なくとも2000年からWindowsに存在し、Windows 10でも引き続き使用されています。

14
HooliganCoder

このディスク情報を取り出すために、「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
12
Mick

これを行う唯一の確実な方法は、すべての_\\.\Physicaldiskx_でCreateFile()を呼び出すことです。ここで、xは0〜15です(16は許可されるディスクの最大数です)。返されたハンドル値を確認してください。無効な場合は、ERROR_FILE_NOT_FOUNDGetLastError()を確認してください。他の何かを返す場合、ディスクは存在しますが、何らかの理由でアクセスできません。

10
anni

唯一の正しい答えは@Grodriguezによるものであり、これは彼が書くのが面倒だったコードです:

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

Windows Driver Development Kitのインストールは非常に時間がかかると思うので、このタスクにDeviceIoControlを使用するために必要な宣言を含めました。

8
polkovnikov.ph

GetLogicalDrives()は、マウントされているすべてのディスクパーティション、not物理ドライブを列挙します。

GetLogicalDrivesを使用して(または使用せずに)ドライブ文字を列挙し、QueryDosDevice()を呼び出して、文字がどの物理ドライブにマップされているかを確認できます。

または、HKEY_LOCAL_MACHINE\SYSTEM\MountedDevicesにあるレジストリの情報をデコードできます。ただし、そこにあるバイナリデータのエンコーディングは明らかではありません。 RussinovichとSolomonの本Microsoft Windows Internalsのコピーがある場合、このレジストリHiveについては第10章で説明します。

8
Die in Sente

Thic WMICコマンドの組み合わせは正常に機能します。

wmic volume list brief
2
user2506992

古いA:およびB:ドライブを含めたいと思うかもしれません。 USBドライブがReadyboost専用の2つのSDHCドライブにぶつかるのにうんざりしました。私はそれらを大文字のZに割り当てていました:Y:あなたが望むようにデバイスにドライブ文字を割り当てるユーティリティで。私は疑問に思った.... Readyboostドライブ文字Aを作成できますか?はい! 2番目のSDHCドライブ文字をBとして入力できますか?はい!

私はその日、フロッピードライブを使用していましたが、A:やB:がReadyboostに役立つとは思っていませんでした。

私のポイントは、A:&B:は誰にも使用されないと仮定しないことです。古いSUBSTコマンドが使用されていることさえあります。

2
liverwort

今日、私はRSSリーダーでこれに出くわしました。よりクリーンなソリューションをお届けします。この例はDelphiにありますが、非常に簡単にC/C++に変換できます(すべてWin32です)。

次のレジストリの場所からすべての値の名前を照会します:HKLM\SYSTEM\MountedDevices

1つずつ、次の関数に渡すと、デバイス名が返されます。かなりきれいでシンプル! このコードはブログで見つけました。

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

ここは、newの解決策ですWMI呼び出しを行うことで。
それから、あなたがする必要があるのはただ電話するだけです:

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

「物理」アクセスが必要な場合は、最終的にストレージデバイスと通信できるようにするこのAPIを開発しています。それはオープンソースであり、いくつかの情報については現在のコードを見ることができます。その他の機能を確認してください: https://github.com/virtium/vtStor

1
phandinhlan