【问题标题】:WMI: Win32_DiskDrive to get total sector on the physical disk driveWMI:Win32_DiskDrive 获取物理磁盘驱动器上的总扇区
【发布时间】:2012-04-11 16:59:07
【问题描述】:

我尝试使用Win32_DiskDrive 获取磁盘的最大总扇区,但它们都返回了不正确的值。我使用了HxD,这个程序返回了准确的值。我尝试使用 fdisk 获取 Linux 中的总扇区,它也可以准确返回。

我注意到Win32_DiskDrive MSDN 中有一条注释如下:

该属性的值是通过 BIOS 中断 13h 的扩展函数获得的。如果驱动器使用转换方案来支持大容量磁盘大小,则该值可能不准确。请咨询制造商以了解准确的驱动器规格。

但我不明白这是什么意思?以及如何解决这个问题?

更新 1:

这是我的 python 脚本的片段代码。

必填:PythonPyWin32WMI

import wmi

c = wmi.WMI()
for diskDrive in c.query("SELECT * FROM Win32_DiskDrive"):
    print diskDrive.Name, "\nTotal Sector: ", diskDrive.TotalSectors

更新 2:

根据要求,这是检测到 HxD 总扇区的 WMI 片段。

  • WMI: 625137345(顶部)
  • HxD: 625142448(底部)

更新 3:

如果有人有兴趣,你也可以在自己的电脑上试试,看看 Win32_DiskDrive 报告的结果是否准确。我用其他存储设备(硬盘、闪存盘等)在许多其他计算机(WinXP 和 7) 上尝试过此操作,但所有结果都不准确。

要尝试请安装PythonPyWin32WMI

非常感谢

【问题讨论】:

  • 您提到的注释没有提到Win32_DiskDrive WMI 类的BytesPerSector 属性,那么您从哪里获得该信息?
  • @RRUZ 抱歉,我刚刚解决了我的问题,我的意思不是扇区大小,而是“总扇区”。
  • 你的代码在哪里?您到底想在哪个平台上执行此操作?
  • @ChibuezeOpata:我已经更新了我的问题以提供一些代码片段。

标签: python winapi wmi disk pywin32


【解决方案1】:

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 就会按照您最初的预期工作。

【讨论】:

    【解决方案2】:

    你这样说 sn-p 不适用于特定的 HDD?您能否告诉我们这个硬盘的详细信息以及您是如何知道它不正确的。

    但是,请尝试使用纯 winapi 方法。 DeviceIoControl 可用于舒适地完成此操作。在 cpp 中查看 complete code listing

    我知道有一种方法可以在 python 中编写 c++,所以祝你好运:)

    【讨论】:

    • sn-p 适用于任何 HDD,只是结果小于 HxD 应用程序的结果。 HxD 检测到的扇区多于 WinAPI 检测到的扇区。本来,我是从C语言出来做的DeviceIoControl,但是结果也少了。然后我用Python尝试WMI,结果也少了。我试图在另一台具有不同磁盘的机器上运行,使用这个 WinAPI 的结果总是比 HxD Detect 少。
    • 据我所知,WINAPI 应该提供最好的准确性。其他可能性可能是您的磁盘行为异常或 HxD 错误。您可以在此处发布不同的值大小吗?
    • 我刚刚上传了问题更新 2 中的屏幕截图。你说得对,WINAPI 总是提供最好的准确性。但在Win32_DiskDrive 里,有一条说明是这样说的。 The value may be inaccurate if the drive uses a translation scheme to support high-capacity disk sizes.。我不太明白这个注释是什么意思。如何解决这个问题。为什么 HxD 可以检测到正确的值..
    • 您没有添加 WINAPI 返回的内容?
    • Win32_DiskDrive 将有关DiskDrive property 的所有信息返回给我。所以我只是访问它的属性(SectorSize)。对不起,如果我误解了,因为我不明白你所说的 WINAPI Returns 的意思
    【解决方案3】:

    我在使用用户 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()
    

    【讨论】:

    • 欢迎来到 StackOverflow。虽然此代码可能会回答问题,但提供有关 如何 和/或 为什么 解决问题的附加上下文将提高​​答案的长期价值。
    猜你喜欢
    • 2021-06-19
    • 2013-10-05
    • 1970-01-01
    • 2023-03-23
    • 2011-06-21
    • 1970-01-01
    • 1970-01-01
    • 2010-12-17
    • 2011-01-10
    相关资源
    最近更新 更多