2008-11-29 6 views

ответ

57

WMIC

wmic очень полный набор инструментов

wmic diskdrive list 

обеспечивают (слишком много) подробный список, например

за меньшие информации

wmic diskdrive list brief 

C

Sebastian Godelet упоминает in the comments:

В C:

system("wmic diskdrive list"); 

PowerShell

Или с помощью PowerShell:

Get-WmiObject Win32_DiskDrive 
+8

-1 Не отвечает на вопрос, который просит о том, как сделать это в C. – unixman83 2012-02-16 13:26:43

+8

+1 Не отвечает на вопрос, но это очень полезная информация :-) – Grodriguez 2012-07-27 07:53:33

+7

вы можете сделать `system (« wmic diskdrive list »);` in C – Sebastian 2012-11-21 13:28:28

8

GetLogicalDrives() перебирает все смонтированные разделы диска, не физические устройства.

Вы можете перечислить буквы дисков с (или без) GetLogicalDrives, а затем вызвать QueryDosDevice(), чтобы узнать, к какому физическому диску сопоставляется буква.

В качестве альтернативы вы можете декодировать информацию в реестре по HKEY_LOCAL_MACHINE \ SYSTEM \ MountedDevices. Однако кодировки двоичных данных там не очевидны. Если у вас есть копия книги Руссиновича и Соломона Microsoft Windows Internals, этот куст реестра обсуждается в главе 10.

+0

вы можете предоставить пример кода? – 2012-03-15 14:35:45

+1

QueryDosDevice ретунирует раздел, а не сам диск. Одиночный диск разделен на C: и D :, Win7 x64. Итак: c => "\ Device \ HarddiskVolume2"; d => "\ Device \ HarddiskVolume3 '" – 2012-07-25 12:47:02

12

Я изменил программу с открытым исходным кодом под названием «dskwipe», чтобы вытащить из нее эту информацию о диске , Dskwipe написан на C, и вы можете вытащить эту функцию из него. Двоичный и источник доступны здесь: dskwipe 0.3 has been released

возвращаемая информация будет выглядеть примерно так:

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 
+1

Я думал, что это так, но он заставляет грубый поиск дисков. Не существует ли api, который только что сообщит об устройствах? – CiNN 2008-12-09 23:03:06

+2

Да. SetupApi в Win32, имена функций начинаются с SetupDi – 2011-12-16 20:06:50

1

Я просто наткнулся на это в моем RSS Reader сегодня. У меня есть более чистое решение для вас. Этот пример находится в Delphi, но может быть легко преобразован в C/C++ (это все Win32).

Запрос все имена значений из следующего реестра: HKLM \ SYSTEM \ MountedDevices

один за другим, передать их в следующей функции и вы будете возвращены имя устройства. Довольно чисто и просто! I found this code on a blog here.

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; 
+2

Я хочу иметь физическое имя, чтобы я мог играть с нераспределенным пространством, поэтому я предполагаю, что это нераспределенное пространство не будет иметь установленный том guid ... – CiNN 2008-12-12 08:45:48

+1

'Fraid this isn 't то, что мы ищем, и похоже на ответ @ Alnitak. – 2010-10-28 10:30:07

+1

Предполагается использовать SetupApi в Windows XP и более поздних версиях и больше не использовать реестр, который был способом сделать это в Win98, но не более того. – 2011-12-16 20:07:19

-1

Составьте список всех писем в США английского алфавита, пропуская & б. "CDEFGHIJKLMNOPQRSTUVWXYZ". Откройте каждый из этих дисков с помощью CreateFile, например.CreateFile("\\.\C:"). Если он не возвращает INVALID_HANDLE_VALUE, тогда у вас есть «хороший» диск. Затем возьмите эту ручку и запустите ее через DeviceIoControl, чтобы получить диск #. See my related answer for more details.

9

Единственный верный способ сделать это - позвонить CreateFile() на всех \\.\Physicaldiskx, где x от 0 до 15 (16 - максимальное количество разрешенных дисков). Проверьте возвращаемое значение дескриптора. Если неверная проверка GetLastError() для ERROR_FILE_NOT_FOUND. Если он возвращает что-то еще, то диск существует, но по какой-то причине вы не можете получить к нему доступ.

37

Один из способов сделать это:

  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); 
    

Это возвращает информацию о физическом местоположении логического тома, а a VOLUME_DISK_EXTENTS Структура.

В простом случае, когда объем проживает на одном физическом диске, номер физического диск доступен в diskExtents.Extents[0].DiskNumber

2
комбинация команды

Thic WMIC работает отлично:

wmic volume list brief 
24

Это может быть 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; 
} 
2

может включить старый A: и B: диски, как вы никогда не знаете, кто может их использовать! Я устал от USB-накопителей, натыкающихся на два диска SDHC, которые предназначены только для Readyboost. Я назначил их Высоким буквам Z: Y: с помощью утилиты, которая будет назначать буквы дисков устройствам по вашему желанию. Я задавался вопросом ... Могу ли я сделать букву с буквой A:? ДА! Могу ли я поставить вторую букву диска SDHC как B:? ДА!

Я использовал флоппи-дисководы в тот же день, никогда не думал, что A: или B: пригодится для Readyboost.

Моя точка зрения, не принимайте A: & B: никого не будет использовать Возможно, вы даже найдете использованную команду SUBST!

8

Единственный правильный ответ является один на @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, это достаточно длительный процесс, так Я включил декларации, которые нужно использовать для этой задачи DeviceIoControl.

1

Если вы хотите получить «физический» доступ, мы разрабатываем этот API, который в конечном итоге позволит вам общаться с устройствами хранения. Это с открытым исходным кодом, и вы можете увидеть текущий код для получения некоторой информации. Проверьте назад для получения дополнительных функций: https://github.com/virtium/vtStor

9

Ответ намного проще, чем все приведенные выше ответы. Список физических дисков фактически хранится в ключе реестра, который также дает сопоставление устройства.

HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services \ диск \ Enum

граф этого число PhysicalDrive # и каждый номер реестр Значение представляет собой соответствующий физический диск.

Например, значение реестра «0» - PhysicalDrive0. Значение - это фактическое устройство, на которое отображается физический диск. Значение, содержащееся здесь, может быть передано в CM_Locate_DevNode в параметре pDeviceID для использования услуг plug and play. Это позволит вам собрать массу информации на устройстве. Например, свойства диспетчера устройств, такие как «Friendly Display Name», если вам нужно имя для диска, серийные номера и т. Д.

Там нет необходимости для служб WMI, которые не могут быть запущены в системе или другой повозка, запряженная волами, и эта функция присутствует в Windows, так как, по крайней мере 2000 и продолжает иметь место в ОС Windows 10.

1

Here решение делать это с выполнением WMI-вызовов.
Тогда все, что вам нужно сделать, это просто позвонить:

queryAndPrintResult(L"SELECT * FROM Win32_DiskDrive", L"Name"); 
Смежные вопросы