Як перерахувати фізичні диски?


77

Як перерахувати фізичні диски в Windows? Для того, щоб отримати список "\\\\.\PhysicalDrive0"доступних.

Відповіді:


71

WMIC

wmic - це дуже повний інструмент

wmic diskdrive list

надати (занадто багато) детальний список, наприклад

щоб отримати менше інформації

wmic diskdrive list brief 

C.

Себастьян Годелет згадує в коментарях :

У C:

Як зазначалося, ви також можете викликати WinAPI, але ... як показано в " Як отримати дані з WMI за допомогою програми C? ", Це досить складно (і, як правило, це робиться на C ++, а не на C).

PowerShell

Або з PowerShell:


9
-1 Не відповідає на запитання, яке задає питання про те, як це зробити в C.
unixman83

12
+1 не відповідає на запитання, але це дуже корисна інформація :-)
Гродрігес,

8
ти міг би зробити це system("wmic diskdrive list");в С
Себастьян

Ви також можете використовувати WMI через WinApi, а не просто викликати програму wmic.
Олексій П.

Win32_DiskDrive не містить фізичного диска, коли програмний наліт або StorageSpaces увімкнено. Оригінальні фізичні диски відфільтровано. Легко порівняти з PowerShell Get-PhysicalDisk
Дмитро Гусаров

46

Один із способів зробити це:

  1. Перерахуйте логічні диски за допомогою GetLogicalDrives

  2. Для кожного логічного диска відкрийте файл з іменем "\\.\X:"(без лапок), де X - буква логічного диска.

  3. Виклик DeviceIoControlпередачі дескриптора файлу, відкритому на попередньому кроці, і dwIoControlCodeпараметру встановлено значення IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS:

Це повертає інформацію про фізичне розташування логічного тому як VOLUME_DISK_EXTENTSструктури.

У простому випадку, коли обсяг знаходиться на одному фізичному диску, номер фізичного диска доступний у diskExtents.Extents[0].DiskNumber


8
Що робити, якщо є порожній диск без жодних (змонтованих) томів?
j_kubik

2
Зауважте, що запропонована ним реалізація DeviceIoControl(IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS)виклику не вдасться, якщо том охоплює кілька дисків. Іншими словами, спочатку потрібно запитати DeviceIoControlрозмір VOLUME_DISK_EXTENTSструктури, потім виділити стільки пам’яті, а вже потім знову викликати її із виділеним буфером. Це працює, як показано вище, оскільки більшість томів розміщуються лише на одному диску.
ahmd0

вибачте, я не можу успішно відкрити "\\. \ C:", використовуючи CreateFile ((_ T ("\\. \ C:"), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE, FILE, FILE / * FILE_FLAG_WRITE_THROUGH | * / FILE_FLAG_NO_BUFFERING, NULL); Не могли б ви зрозуміти мою проблему?
лучник,

@ ahmd0 VOLUME_DISK_EXTENTSзберігає достатньо пам’яті для одного екстенту , тож ви можете назвати його так, як пропонує Гродрігес, а потім перевірити, success || ERROR_MORE_DATA == GetLastError()оскільки ми в будь-якому випадку дбаємо лише про перший екстент .
Міллі Сміт

1
Використовуйте 0 замість GENERIC_READ, це дозволить відкрити диск навіть без прав адміністратора, але все одно ви зможете читати метаінформацію, як-от розширення диска.
ivan.ukr

33

Це може бути на 5 років запізно :). Але оскільки я поки що не бачу відповіді на це, додаючи це.

Ми можемо використовувати API налаштування, щоб отримати список дисків, тобто пристроїв у системі, що реалізують GUID_DEVINTERFACE_DISK.

Після того як ми їх шляху пристроїв, ми можемо видати IOCTL_STORAGE_GET_DEVICE_NUMBERпобудувати "\\.\PHYSICALDRIVE%d"зSTORAGE_DEVICE_NUMBER.DeviceNumber

Див. Також SetupDiGetClassDevsфункцію


Додавання іншого посилання (у мене не було достатньо представників, щоб розмістити у відповіді) Функції API налаштування
arun

1
Звучить цікаво. Повніше, ніж моя відповідь вище. +1
VonC

зауважте, що в цих функціях SetupAPI будуть перераховані не лише всі фізичні диски, а й віртуальні - насправді буде перераховано кожен зареєстрований інтерфейс дисковода , і це може бути вирішенням питання, але це також дасть багато "шумових даних", використання SetupAPI набагато складніше, ніж пропонується у цій відповіді
спеціаліст

Я написав невелику бібліотеку під назвою libwindevblk на основі відповіді вище, що дисководи списку отримують імена томів, коли це можливо, і надаю API, що дозволяє читати / писати просто на розділах
Вінсент Річ

19

Відповідь набагато простіший, ніж усі вищезазначені відповіді. Список фізичних накопичувачів фактично зберігається в ключі реєстру, який також надає відображення пристрою.

HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services \ disk \ Enum

Count - це число PhysicalDrive #, а кожне пронумероване значення реєстру - це відповідний фізичний диск.

Наприклад, значенням реєстру "0" є PhysicalDrive0. Значення - це фактичний пристрій, на який відображається пристрій PhysicalDrive0. Значення, що міститься тут, може бути передане в CM_Locate_DevNode в межах параметра pDeviceID для використання служб підключення та відтворення. Це дозволить вам зібрати велику кількість інформації на пристрої. Такі властивості з Диспетчера пристроїв, як "Дружнє відображуване ім'я", якщо вам потрібно ім'я для накопичувача, серійні номери тощо.

Немає необхідності в послугах WMI, які можуть не працювати в системі чи інших хакерських системах, і ця функціональність присутня в Windows щонайменше з 2000 року і продовжує бути такою в Windows 10.


Цікава альтернатива, ймовірно, більш доречна, ніж моя відповідь 7+ років. +1
VonC

На мою думку, найкращий варіант, оскільки він простий, надійний, і використання реєстру - це, мабуть, те, що хотіли розробники Windows при оформленні вікон.
felknight

Набагато кращий варіант, ніж моя відповідь, +1. Останнє питання - чому він повинен містити фактичну інформацію. Це задокументовано? В який момент Windows записує дані туди? Чи використовує це консоль управління?
polkovnikov.ph

Відмінний метод, але у нього є один невеликий недолік: він не може перерахувати кожен фізичний розмір накопичувача, оскільки вони не зберігаються в реєстрі (хоча служби WMI їх надають). Для таких речей, як отримання виробника та моделі кожного накопичувача, це все одно набагато краще та менш ресурсомістке, тому +1 від мене. Мені потрібно отримати розмір кожного накопичувача, і я не використовую це в C, тому мені доведеться піти шляхом WMI. Це більш-менш та сама історія, що і з фізичною пам’яттю, детальні дані якої також не зберігаються в реєстрі ...
Інь Когніто,

"присутній у Windows принаймні з 2000 року": Не вдається підтвердити. Ключ реєстру відсутній у Windows XP та Windows 7.
Томас,

12

Я модифікував програму з відкритим кодом "dskwipe", щоб витягти з неї цю інформацію про диск. Dskwipe написано на мові C, і ви можете витягти з нього цю функцію. Бінарний файл та джерело доступні тут: випущено dskwipe 0.3

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


1
я думав, що це все, але це змушує грубий пошук дисків .. чи не існує API, який просто звітує про пристрої?
CiNN

2
Так. SetupApi у Win32, назви функцій починаються з SetupDi
Warren P

11

Єдиною правильною відповіддю є відповідь @Grodriguez, і ось код, який він лінувався писати:

Я думаю, що встановлення Windows Driver Development Kit є досить тривалим процесом, тому я включив декларації, які потрібно використовувати DeviceIoControlдля цього завдання.


2
також: перевизначення макросів Windows може бути просто найгіршою ідеєю за всю історію - така програма досить швидко зламається і перестане працювати.
спеціалізація

2
Як я показав у своєму коментарі до цієї відповіді, ви телефонуєте DeviceIoControlнеправильно. Ви не можете припустити, що існує лише одна міра. Вам потрібно запитати DeviceIoControlпро розмір необхідного VOLUME_DISK_EXTENTSбуфера.
ahmd0

@ ahmd0 Буду радий це виправити. Не могли б ви вказати на сторінку msdn, яка описує таку поведінку, будь ласка? (Хоча спосіб створення диска, який знаходиться на двох ступенях, теж буде нормальним, оскільки я просто не знайшов способу перевірити його.)
polkovnikov.ph

@ polkovnikov.ph: msdn.microsoft.com/en-us/library/windows/desktop/aa365727.aspx Ви в основному закликаєте DeviceIoControlпам'ять до такого синглу, VOLUME_DISK_EXTENTSяк ви робили, але потім перевіряєте, чи він не вдався, і якщо так, то подивіться, чи повернувся він ERROR_MORE_DATAв GetLastErrorі якщо так, то виділити новий буфер для NumberOfDiskExtentsряду DISK_EXTENTструктур (що він повернувся) і зателефонувати DeviceIoControlще раз і переконайтеся , що це вдасться. Ви, очевидно, не робите всього цього, якщо перший заклик до DeviceIoControlуспіху.
ahmd0

1
Не кожен фізичний диск буде пов'язаний з логічним диском, і навіть тоді не кожному логічному диску буде присвоєна буква диска.
anni

10

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


7
Звідки у вас цей номер?
слабкий спаз

1
Чому обмежуватися 15? Продовжуйте підраховувати, поки не провалитесь. Я не впевнений, що якийсь номер пристрою буде пропущений ОС.
Аджай

1
@Ajay, я найкраще здогадуюсь, якщо ви підключите пристрій A, підключіть пристрій B, а потім відключите пристрій A
Howl

9

GetLogicDrives () перераховує всі змонтовані розділи диска, а не фізичні диски.

Ви можете перерахувати букви накопичувача за допомогою (або без) GetLogicDrives, а потім зателефонувати QueryDosDevice (), щоб дізнатись, на який фізичний диск призначається лист.

Ви також можете декодувати інформацію в реєстрі за адресою HKEY_LOCAL_MACHINE \ SYSTEM \ MountedDevices. Проте кодування двійкових даних там не є очевидним. Якщо у вас є копія книги Русіновича та Соломона Microsoft Windows Internals, цей вулик реєстру обговорюється в розділі 10.


1
QueryDosDevice реконструює розділ, а не сам диск. Один диск розділений на C: і D :, Win7 x64. Отже: c => "\ Device \ HarddiskVolume2"; d => "\ Device \ HarddiskVolume3 '"
Arioch'

4

Товста комбінація команд WMIC чудово працює:


томи! = фізичні диски. Ця команда не буде перераховувати фізичні диски, що містять нульові томи, такі як неініціалізовані диски. (Крім того, хоча це не є фатальною проблемою, як попередня, результат цієї команди потребуватиме подальшої обробки для дедуплікації ідентифікаторів фізичних дисків, що містять кілька томів.)
Кіт Рассел,

2

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

Я раніше використовував флоппі-диски, ніколи не думав, що A: або B: стане в нагоді для Readyboost.

Моя думка полягає в тому, що не припускайте, що A: & B: ні для кого не буде використовуватися. Ви навіть можете виявити, що використовується стара команда SUBST!


1

Я щойно натрапив на це у своєму RSS Reader сьогодні. У мене є більш чисте рішення для вас. Цей приклад є в Delphi, але його дуже легко перетворити на C / C ++ (це все Win32).

Запитуйте всі імена значень із такого розташування реєстру: HKLM \ SYSTEM \ MountedDevices

По черзі передайте їх у наступну функцію, і вам буде повернуто ім’я пристрою. Досить чисто і просто! Я знайшов цей код у своєму блозі тут.


2
я хочу мати фізичне ім'я, щоб я міг грати з нерозподіленим простором, тому, на мою думку, цей нерозподілений простір не мав би змонтованого
керуючого

1
`` Зважаючи на те, що це не те, що ми шукаємо, це схоже на відповідь @ Alnitak.
Matt Joiner

1
Ви повинні використовувати SetupApi у Windows XP та пізніших версіях і більше не використовувати реєстр, як це було зроблено в Win98, але більше не.
Warren P

1

Якщо ви хочете отримати "фізичний" доступ, ми розробляємо цей API, який врешті-решт дозволить вам спілкуватися з пристроями зберігання даних. Це відкритий код, і ви можете побачити поточний код для деякої інформації. Перевірте ще більше функцій: https://github.com/virtium/vtStor


1

Ось це нове рішення робить це з виконанням викликів WMI.
Тоді все, що вам потрібно зробити, це просто зателефонувати:


0

Якщо вам потрібно лише переглянути існуючі диски, цього буде достатньо:


Завжди пишіть свої відповіді з деталями, наприклад, як це працює, і якщо це не працює для ОП, то вкажіть причину цього, перевірте це посилання для отримання додаткової інформації. stackoverflow.com/help/how-to-answer
Даніал Ahmad

-3

Складіть список усіх літер в американському алфавіті, пропускаючи a & b. "CDEFGHIJKLMNOPQRSTUVWXYZ". Відкрийте кожен із цих накопичувачів, CreateFileнаприклад CreateFile("\\.\C:"). Якщо він не повертається, INVALID_HANDLE_VALUEви отримали "хороший" привід. Далі візьміть цей дескриптор і проведіть його, DeviceIoControlщоб отримати номер диска. Докладнішу інформацію див. У моїй відповіді .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.