Làm thế nào để liệt kê các đĩa vật lý?


77

Làm thế nào để liệt kê các đĩa vật lý trong Windows? Để có được một danh sách "\\\\.\PhysicalDrive0"có sẵn.

Câu trả lời:


71

WMIC

wmic là một công cụ rất hoàn chỉnh

wmic diskdrive list

cung cấp một danh sách chi tiết (quá nhiều), chẳng hạn

để biết ít thông tin hơn

wmic diskdrive list brief 

C

Sebastian Godelet đề cập trong các bình luận :

Trong C:

Như đã nhận xét, bạn cũng có thể gọi WinAPI, nhưng ... như được hiển thị trong " Cách lấy dữ liệu từ WMI bằng ứng dụng C? ", Điều này khá phức tạp (và thường được thực hiện với C ++, không phải C).

PowerShell

Hoặc với PowerShell:


9
-1 không trả lời câu hỏi, đó là yêu cầu cho làm thế nào để làm điều đó trong C.
unixman83

12
1 Không trả lời câu hỏi, nhưng nó là một mảnh rất hữu ích của thông tin :-)
Grodriguez

8
bạn có thể làm một system("wmic diskdrive list");trong C
Sebastian

Bạn cũng có thể sử dụng WMI thông qua WinApi, không chỉ gọi ứng dụng wmic.
Alex P.

Win32_DiskDrive không liệt kê đĩa vật lý khi kích hoạt phần mềm đột kích hoặc StorageSpaces. Các đĩa vật lý ban đầu đã được lọc ra. Dễ dàng so sánh với PowerShell Get-PhysicalDisk
Dmitry Gusarov.

46

Một cách để làm điều đó:

  1. Liệt kê các ổ đĩa logic bằng cách sử dụng GetLogicalDrives

  2. Đối với mỗi ổ đĩa logic, hãy mở một tệp có tên "\\.\X:"(không có dấu ngoặc kép) trong đó X là ký tự ổ đĩa logic.

  3. Lệnh gọi DeviceIoControlchuyển xử lý tới tệp đã mở ở bước trước và dwIoControlCodetham số được đặt thành IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS:

Điều này trả về thông tin về vị trí thực của một khối logic, như một VOLUME_DISK_EXTENTScấu trúc.

Trong trường hợp đơn giản khi ổ đĩa nằm trên một ổ đĩa vật lý, số ổ đĩa vật lý có sẵn trong diskExtents.Extents[0].DiskNumber


8
Điều gì sẽ xảy ra nếu có một đĩa trống không có bất kỳ ổ đĩa (được gắn) nào?
j_kubik

2
Lưu ý rằng việc triển khai DeviceIoControl(IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS)cuộc gọi được đề xuất của anh ấy sẽ không thành công nếu một ổ đĩa trải dài trên nhiều đĩa. Nói cách khác, trước tiên bạn cần hỏi DeviceIoControlkích thước của VOLUME_DISK_EXTENTSstruct, sau đó cấp phát lượng bộ nhớ đó, và chỉ sau đó gọi lại nó bằng bộ đệm được cấp phát. Nó hoạt động theo cách được hiển thị ở trên vì hầu hết các ổ đĩa chỉ nằm trên một đĩa.
ahmd0

xin lỗi, tôi không thể mở "\\. \ C:" thành công bằng cách sử dụng CreateFile ((_ T ("\\. \ C:"), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, // / * FILE_FLAG_WRITE_THROUGH | * / FILE_FLAG_NO_BUFFERING, NULL); Bạn có thể tìm ra vấn đề của tôi không?
bowman han

@ ahmd0 VOLUME_DISK_EXTENTScó đủ bộ nhớ cho một phạm vi, vì vậy bạn có thể gọi nó như Grodriguez đề xuất và sau đó kiểm tra success || ERROR_MORE_DATA == GetLastError()vì dù sao chúng tôi cũng chỉ quan tâm đến phạm vi đầu tiên.
Millie Smith

1
Sử dụng 0 thay vì GENERIC_READ, điều này sẽ cho phép đĩa mở ngay cả khi có đặc quyền quản trị viên, nhưng bạn vẫn có thể đọc thông tin meta như dung lượng đĩa.
ivan.ukr

33

Điều này có thể là quá muộn 5 năm :). Nhưng khi tôi thấy chưa có câu trả lời cho điều này, thêm điều này.

Chúng ta có thể sử dụng các API thiết lập để lấy danh sách các ổ đĩa tức là các thiết bị trong hệ thống đang triển khai GUID_DEVINTERFACE_DISK.

Sau khi chúng tôi có đường dẫn thiết bị của họ, chúng tôi có thể phát IOCTL_STORAGE_GET_DEVICE_NUMBERtriển "\\.\PHYSICALDRIVE%d"vớiSTORAGE_DEVICE_NUMBER.DeviceNumber

Xem thêm SetupDiGetClassDevschức năng


Thêm một liên kết khác (tôi không có đủ đại diện để đăng câu trả lời) Thiết lập chức năng API
arun

1
Nghe có vẻ thú vị. Hoàn thiện hơn câu trả lời của tôi ở trên. +1
VonC

lưu ý rằng các hàm SetupAPI này sẽ không chỉ liệt kê tất cả các ổ đĩa vật lý mà còn cả các ổ đĩa ảo - trên thực tế, mọi giao diện ổ đĩa đã đăng ký sẽ được liệt kê, điều này có thể là giải pháp cho câu hỏi nhưng nó cũng sẽ tạo ra rất nhiều "dữ liệu nhiễu", sử dụng SetupAPI phức tạp hơn nhiều so với những gì được đề xuất trong câu trả lời này
specializt

Tôi đã viết một thư viện nhỏ có tên libwindevblk dựa trên câu trả lời ở trên để liệt kê các ổ đĩa, truy xuất tên ổ đĩa khi có thể và cung cấp một api cho phép đọc / ghi đơn giản trên các phân vùng
Vincent Rich

19

Câu trả lời đơn giản hơn nhiều so với tất cả các câu trả lời trên. Danh sách ổ đĩa vật lý thực sự được lưu trữ trong khóa Registry, khóa này cũng cung cấp cho ánh xạ thiết bị.

HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services \ disk \ Enum

Đếm là số PhysicalDrive # và mỗi Giá trị đăng ký được đánh số là ổ vật lý tương ứng.

Ví dụ: Giá trị sổ đăng ký "0" là PhysicalDrive0. Giá trị là thiết bị thực tế PhysicalDrive0 được ánh xạ tới. Giá trị chứa ở đây có thể được chuyển vào CM_Locate_DevNode trong tham số pDeviceID để sử dụng các dịch vụ plug and play. Điều này sẽ cho phép bạn thu thập nhiều thông tin trên thiết bị. Chẳng hạn như các thuộc tính từ Trình quản lý thiết bị như "Tên hiển thị thân thiện" nếu bạn cần tên cho ổ đĩa, số sê-ri và hơn thế nữa.

Không cần các dịch vụ WMI có thể không chạy trên hệ thống hoặc các phương thức hack khác và chức năng này đã có mặt trong Windows ít nhất từ ​​năm 2000 và tiếp tục là trường hợp của Windows 10.


Thay thế thú vị, có lẽ phù hợp hơn câu trả lời trên 7 tuổi của tôi. +1
VonC

Tùy chọn tốt nhất theo ý kiến ​​của tôi, vì nó đơn giản, đáng tin cậy và việc sử dụng sổ đăng ký có lẽ là điều mà các nhà phát triển cửa sổ muốn khi mô tả cửa sổ.
felknight

Lựa chọn tốt hơn nhiều so với câu trả lời của tôi, +1. Câu hỏi cuối cùng là tại sao nó phải chứa thông tin thực tế. Nó có được ghi lại không? Tại thời điểm nào Windows ghi dữ liệu vào đó? Bảng điều khiển quản lý có sử dụng nó không?
polkovnikov.ph

Phương pháp tuyệt vời, nhưng nó có một nhược điểm nhỏ: nó không thể liệt kê từng kích thước ổ đĩa vật lý, vì chúng không được lưu trữ trong sổ đăng ký (mặc dù các dịch vụ WMI cung cấp chúng). Đối với những thứ như nhận nhà sản xuất và kiểu máy của mỗi ổ đĩa, nó vẫn tốt hơn nhiều và ít tốn tài nguyên hơn, vì vậy hãy +1 từ tôi. Tôi cần lấy kích thước của mỗi ổ đĩa và tôi không sử dụng nó trong C, vì vậy tôi sẽ phải sử dụng WMI. Đó là nhiều hơn hoặc ít hơn những câu chuyện tương tự như với bộ nhớ vật lý, có dữ liệu chi tiết không được lưu trữ trong registry hoặc ...
Yin Cognyto

"có trong Windows ít nhất từ ​​năm 2000": Không thể xác nhận. Khóa đăng ký bị thiếu trong Windows XP và Windows 7.
Thomas

12

Tôi đã sửa đổi một chương trình mã nguồn mở có tên "dskwipe" để lấy thông tin đĩa này ra khỏi nó. Dskwipe được viết bằng C, và bạn có thể lấy chức năng này ra khỏi nó. Mã nhị phân và mã nguồn có sẵn tại đây: dskwipe 0.3 đã được phát hành

Thông tin trả về sẽ giống như sau:


1
Tôi nghĩ nó là nó, nhưng nó buộc phải tìm kiếm thô bạo cho các ổ đĩa..không phải có một api sẽ chỉ báo cáo lại các thiết bị?
CiNN

2
Đúng. SetupApi trong Win32, tên chức năng bắt đầu bằng SetupDi
Warren P

11

Câu trả lời đúng duy nhất là câu trả lời của @Grodriguez và đây là đoạn mã mà anh ấy quá lười biếng để viết:

Tôi nghĩ rằng việc cài đặt Bộ phát triển trình điều khiển Windows là một quá trình khá dài, vì vậy tôi đã bao gồm các khai báo mà một người cần sử dụng DeviceIoControlcho tác vụ này.


2
Ngoài ra: việc xác định lại macro cửa sổ có thể là ý tưởng tồi tệ nhất từ ​​trước đến nay - một ứng dụng như vậy sẽ sớm bị hỏng và ngừng hoạt động.
specializt

2
Giống như tôi đã hiển thị trong nhận xét của tôi cho câu trả lời này, bạn đang gọi DeviceIoControlkhông chính xác. Bạn không thể cho rằng chỉ có một mức độ. Bạn cần hỏi DeviceIoControlkích thước của VOLUME_DISK_EXTENTSbộ đệm cần thiết .
ahmd0

@ ahmd0 Tôi rất vui khi sửa nó. Bạn có thể chỉ vào trang msdn mô tả hành vi đó không? (Mặc dù cách tạo một đĩa nằm trên hai mức độ cũng sẽ ổn, vì tôi vừa không tìm thấy cách nào để kiểm tra nó.)
polkovnikov.ph 25/10/15

@ polkovnikov.ph: msdn.microsoft.com/en-us/library/windows/desktop/aa365727.aspx Về cơ bản, bạn gọi DeviceIoControlbộ nhớ cho một bộ nhớ VOLUME_DISK_EXTENTSnhư bạn đã làm nhưng sau đó kiểm tra xem nó có bị lỗi không và nếu có, hãy xem nó có trả về không ERROR_MORE_DATAtrong GetLastErrorvà nếu như vậy, bố trí một bộ đệm mới cho NumberOfDiskExtentssố DISK_EXTENTcấu trúc (mà nó trả lại) và gọi DeviceIoControlmột lần nữa và chắc chắn rằng nó thành công. Bạn rõ ràng không làm tất cả những điều này nếu cuộc gọi đầu tiên DeviceIoControlthành công.
ahmd0

1
Không phải mọi ổ đĩa vật lý sẽ được liên kết với một ổ đĩa logic và thậm chí sau đó không phải mọi ổ đĩa logic sẽ được gán một ký tự ổ đĩa.
anni

10

Cách chắc chắn duy nhất để làm điều này là gọi CreateFile()trên tất cả các \\.\Physicaldiskxvị trí x từ 0 đến 15 (16 là số đĩa tối đa được phép). Kiểm tra giá trị xử lý được trả về. Nếu kiểm tra không hợp lệ GetLastError()cho ERROR_FILE_NOT_FOUND . Nếu nó trả về bất kỳ thứ gì khác thì đĩa tồn tại nhưng bạn không thể truy cập vì lý do nào đó.


7
Bạn lấy số này ở đâu?
thinnespase

1
Tại sao giới hạn đến 15? Tiếp tục liệt kê cho đến khi bạn thất bại. Tôi không chắc liệu một số số thiết bị có bị hệ điều hành bỏ qua hay không.
Ajay

1
@Ajay phỏng đoán tốt nhất của tôi là trong trường hợp bạn cắm thiết bị A, cắm thiết bị B, sau đó rút thiết bị A
Howl

9

GetLogicalDrives () liệt kê tất cả các phân vùng đĩa được gắn kết, không phải ổ đĩa vật lý.

Bạn có thể liệt kê các ký tự ổ đĩa có (hoặc không có) GetLogicalDrives, sau đó gọi QueryDosDevice () để tìm ra ổ đĩa vật lý mà ký tự được ánh xạ tới.

Ngoài ra, bạn có thể giải mã thông tin trong sổ đăng ký tại HKEY_LOCAL_MACHINE \ SYSTEM \ MountedDevices. Tuy nhiên, các mã hóa dữ liệu nhị phân ở đó không rõ ràng. Nếu bạn có một bản sao cuốn sách Microsoft Windows Internals của Russinovich và Solomon, tổ hợp đăng ký này sẽ được thảo luận trong Chương 10.


1
QueryDosDevice khôi phục lại phân vùng, không phải chính đĩa. Đĩa đơn được chia thành C: và D :, Win7 x64. Vì vậy: c => "\ Device \ HarddiskVolume2"; d => "\ Device \ HarddiskVolume3 '"
Arioch' The

4

Thic tổ hợp lệnh WMIC hoạt động tốt:


volume! = đĩa vật lý. Lệnh này sẽ không liệt kê các đĩa vật lý có chứa khối lượng bằng không, chẳng hạn như các đĩa chưa được khởi tạo. (Ngoài ra, mặc dù nó không phải là một vấn đề nghiêm trọng như trước đó, đầu ra của lệnh này sẽ yêu cầu tiếp tục xử lý để id deduplicate của đĩa vật lý có chứa nhiều volume.)
Keith Russell

2

Có thể muốn bao gồm các ổ đĩa A: và B: cũ mà bạn không bao giờ biết ai có thể đang sử dụng chúng! Tôi cảm thấy mệt mỏi với việc ổ USB va chạm với hai ổ SDHC chỉ dành cho Readyboost. Tôi đã gán chúng cho các chữ cái Cao Z: Y: với một tiện ích sẽ gán các ký tự ổ đĩa cho các thiết bị như bạn muốn. Tôi tự hỏi .... Tôi có thể tạo ổ đĩa Readyboost ký tự A:? ĐÚNG! Tôi có thể đặt ký tự ổ đĩa SDHC thứ hai của mình là B :? ĐÚNG!

Tôi đã sử dụng Ổ đĩa mềm ngày trước, chưa bao giờ nghĩ rằng A: hoặc B: sẽ có ích cho Readyboost.

Quan điểm của tôi là, đừng cho rằng A: & B: sẽ không được sử dụng bởi bất kỳ ai cho bất cứ điều gì Bạn thậm chí có thể thấy lệnh SUBST cũ đang được sử dụng!


1

Tôi vừa xem qua điều này trong RSS Reader của tôi hôm nay. Tôi có một giải pháp sạch hơn cho bạn. Ví dụ này là trong Delphi, nhưng rất có thể dễ dàng chuyển đổi sang C / C ++ (Tất cả đều là Win32).

Truy vấn tất cả các tên giá trị từ vị trí đăng ký sau: HKLM \ SYSTEM \ MountedDevices

Từng cái một, chuyển chúng vào hàm sau và bạn sẽ được trả về tên thiết bị. Khá sạch sẽ và đơn giản! Tôi tìm thấy mã này trên một blog ở đây.


2
tôi muốn có tên vật lý để tôi có thể chơi với không gian chưa được phân bổ, vì vậy tôi đoán rằng không gian chưa được phân bổ này sẽ không có hướng dẫn âm lượng được gắn kết ...
CiNN 12/12/08

1
'Fraid đây không phải là những gì chúng tôi đang tìm kiếm và tương tự như câu trả lời của @ Alnitak.
Matt Joiner

1
Bạn phải sử dụng SetupApi trong windows xp trở lên và không còn sử dụng sổ đăng ký, đó là cách để làm điều đó trong Win98, nhưng không phải bất kỳ cách nào nữa.
Warren P

1

Nếu bạn muốn có quyền truy cập "vật lý", chúng tôi đang phát triển API này, API này cuối cùng sẽ cho phép bạn giao tiếp với các thiết bị lưu trữ. Đó là mã nguồn mở và bạn có thể xem mã hiện tại để biết một số thông tin. Kiểm tra lại để biết thêm các tính năng: https://github.com/virtium/vtStor


1

Đây là mộtgiải pháp mới để thực hiện nó với việc thực hiện các cuộc gọi WMI.
Sau đó, tất cả những gì bạn cần làm chỉ là gọi:


0

Nếu bạn chỉ cần nhìn vào các đĩa hiện có, cái này sẽ đủ:


Luôn viết câu trả lời của bạn kèm theo chi tiết, như cách nó hoạt động và nếu nó không hoạt động với OP thì hãy đưa ra lý do cho điều đó, hãy kiểm tra liên kết này để biết thêm chi tiết. stackoverflow.com/help/how-to-answer
Daniyal Ahmad

-3

Lập danh sách tất cả các chữ cái trong Bảng chữ cái tiếng Anh Hoa Kỳ, bỏ qua a & b. "CDEFGHIJKLMNOPQRSTUVWXYZ". Mở từng ổ đĩa đó bằng CreateFilevd CreateFile("\\.\C:"). Nếu nó không trở lại INVALID_HANDLE_VALUEthì bạn đã có một ổ đĩa 'tốt'. Tiếp theo, lấy tay cầm đó và chạy nó DeviceIoControlđể lấy Disk #. Xem câu trả lời liên quan của tôi để biết thêm chi tiết .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.