我尝试使用Win32_DiskDrive获取磁盘的最大总扇区,但所有这些都返回了错误的值。我使用了HxD,这个程序返回了准确的值。我试图使用fdisk在Linux中获得整个扇区,它也准确地返回。
我注意到Win32_DiskDrive MSDN 中的注释如下:
此属性的值是通过BIOS中断13h的扩展功能获得的。如果驱动器使用转换方案来支持高容量磁盘大小,则该值可能不准确。有关精确的驱动器规格,请咨询制造商。
但我无法理解这意味着什么?以及如何解决这个问题?
这是我的python脚本的剪辑代码。
import wmi
c = wmi.WMI()
for diskDrive in c.query("SELECT * FROM Win32_DiskDrive"):
print diskDrive.Name, "\nTotal Sector: ", diskDrive.TotalSectors
根据要求,这里是检测到HxD总扇区的WMI片段。
如果有兴趣的话,您也可以在自己的计算机上试一试,看看Win32_DiskDrive是否报告了准确的结果。我在许多其他计算机(WinXP& 7)上尝试使用其他存储设备(硬盘,闪存盘等),但所有结果都不准确。
非常感谢
答案 0 :(得分:2)
WMI报告的驱动器比实际小几MB。我认为这与Windows如何根据柱面/磁头/扇区处理驱动器有关。
我的解决方案是读取报告的驱动器大小的结尾,直到出现错误:
import wmi
disks = wmi.WMI().Win32_DiskDrive(MediaType="Removable Media")
for disk in disks:
disk_size = int(disk.size)
sector_size = disk.BytesPerSector
print(disk.name, "reported size:", disk_size)
with open(disk.name, "rb") as f:
f.seek(disk_size)
while True:
try:
f.read(sector_size)
disk_size += sector_size
except PermissionError:
break
print(disk.name, "readable size:", disk_size)
对于两个不同的32GB SD卡,我得到以下结果:
\\.\PHYSICALDRIVE2 reported size: 31683778560
\\.\PHYSICALDRIVE2 readable size: 31691110400
\\.\PHYSICALDRIVE3 reported size: 31437020160
\\.\PHYSICALDRIVE3 readable size: 31439453184
然而,实际的驱动器实际上还有1024到2048个字节,我们仍然无法读取,而且我不知道如何获取它们。但是,这比我们之前缺少的几MB好。
编辑:似乎buffering导致了读取最后几个字节的问题。如果我open(disk.name, "rb", buffering=0)
,我可以读取剩余的字节。然而,这非常慢(约1MB /秒,相当于其中一个驱动器约7秒)。这可能是一个很好的混合方法,你只使用buffering = 0来读取最后几个字节,并在其余时间使用默认缓冲。
\\.\PHYSICALDRIVE2 reported size: 31683778560
\\.\PHYSICALDRIVE2 readable size: 31691112448 (with buffering=0)
\\.\PHYSICALDRIVE14 reported size: 31437020160
\\.\PHYSICALDRIVE14 readable size: 31439454208 (with buffering=0)
编辑2 :您可以使用read1
获取最后几个字节,而无需使用buffering=0
打开文件。因此,要获得实际的磁盘大小,您可以这样做:
reported_size = disk.size
f.seek(reported_size)
while True:
try: # Read beyond the reported size
f.read(sector_size)
except PermissionError:
easily_readable_size = f.tell()
try: # Get the last few bytes using read1 (unbuffered)
for i in range(128): # Test up to this many additional sectors
f.read1(self.sector_size)
except PermissionError:
actual_size = f.tell()
break
注意我认为您可能无法始终f.read
最多easily_readable_size
,因为内部缓冲区的对齐可能并不总是相同(?)。我将该值减少io.DEFAULT_BUFFER_SIZE
以使其更安全一些。然后我用我自己的函数覆盖了f.read
,该函数在整个磁盘上正确地f.read
透明地f.read
组合了上述内容。这样,{{1}}就会起到预期它首先发挥作用的作用。
答案 1 :(得分:0)
你说这个片段不能用于特定的硬盘吗?你能告诉我们这个硬盘的细节以及你怎么知道它是不正确的。
但是,请尝试使用纯winapi方法。 DeviceIoControl
可用于舒适地。请参阅cpp。中的complete code listing
我知道有一种方法可以在python中编写c ++,这样就可以了。)
答案 2 :(得分:0)
我在使用用户 user3268002 的读取测试解决方案时遇到问题。使用可正常工作的 USB 闪存驱动器,它导致了整整一分钟的冻结,在此期间还使其他应用程序无法访问驱动器列表,甚至一度导致驱动器在重新插入之前无法再访问。根据初始查找位置,报告的大小也不正确,报告太多字节(扇区),因为第一个 read() 调用愉快地读取了末尾之外的几个扇区,无一例外。但它适用于普通硬盘。
以下代码始终为我提供了 HxD 报告的所有测试驱动器的正确大小。
import struct
import win32file #pip install pywin32
import winioctlcon #pip install pywin32
f = win32file.CreateFile('\\\\.\\PHYSICALDRIVE0', win32file.GENERIC_READ, 0, None, win32file.OPEN_EXISTING, win32file.FILE_ATTRIBUTE_NORMAL, 0)
size = win32file.DeviceIoControl(f, winioctlcon.IOCTL_DISK_GET_LENGTH_INFO, None, 512, None) #returns bytes
size = struct.unpack('q', size)[0] #convert 64 bit int from bytes to int -> first element of returned tuple
print(size)
f.close()