相关文章推荐
玩足球的乒乓球  ·  Android soong ...·  1 年前    · 

WMI: Win32_DiskDrive获取物理磁盘驱动器上的总扇区

4 人关注

我曾试着用以下方法获得一个磁盘的最大总扇区 Win32_DiskDrive 但所有这些都返回不正确的值。我使用了 HxD 而这个程序返回的是准确的值。我试着在Linux中用fdisk来获取总扇区,它也能准确地返回。

我注意到,在 "我 "字中有一个注释。 Win32_DiskDrive MSDN 如下所示。

该属性的值是通过BIOS中断13h的扩展功能获得的。如果硬盘使用转换方案来支持大容量的磁盘尺寸,该值可能不准确。请咨询制造商以获得准确的硬盘规格。

但我不明白这意味着什么,以及如何解决这个问题?

Update 1:

下面是我的Python脚本的剪贴代码。

Required: Python , PyWin32 , WMI

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

Update 2:

按照要求,这里是检测到HxD总扇区的WMI片段。

  • WMI: 625137345 (Top)
  • HxD: 625142448 (Bottom)
  • Update 3:

    如果有人感兴趣,你也可以在自己的电脑上试试,看看Win32_DiskDrive的报告是否准确。我在许多其他电脑上试过这个方法(WinXP & 7)与其他存储设备(硬盘、闪存盘,等等),但所有的结果都是不准确的。

    要尝试,请安装Python, PyWin32, WMI

    非常感谢您

    4 个评论
    RRUZ
    你提到的说明中没有提到 BytesPerSector 的属性。 Win32_DiskDrive WMI类,那么你从哪里得到这些信息?
    Yeo
    @RRUZ 对不起,我刚刚修改了我的问题,我的意思不是指部门大小,而是指 "总部门"。
    你的代码在哪里?你到底想在什么平台上做这个?
    Yeo
    @ChibuezeOpata:我已经更新了我的问题,提供了一些剪接代码。
    python
    winapi
    wmi
    disk
    pywin32
    Yeo
    Yeo
    发布于 2012-03-28
    3 个回答
    user3268002
    user3268002
    发布于 2021-06-23
    已采纳
    0 人赞同

    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:
                    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要好。

    Edit: Seems like the buffering导致读取最后几个字节的问题。如果我做open(disk.name, "rb", buffering=0),我可以读取剩余的字节。然而,这非常慢(~1MB/秒,相当于其中一个驱动器的7秒左右)。可能有一个很好的混合方法,你只在读取最后几个字节时使用缓冲=0,其余时间使用默认的缓冲方式。

    \\.\PHYSICALDRIVE2 reported size: 31683778560
    \\.\PHYSICALDRIVE2 readable size: 31691112448 (with buffering=0)
    \\.\PHYSICALDRIVE14 reported size: 31437020160
    \\.\PHYSICALDRIVE14 readable size: 31439454208 (with buffering=0)
    

    Edit 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
    

    Note I think你可能不总是能够f.readeasily_readable_size,因为内部缓冲区的对齐方式可能不总是相同(?)我把这个值减少了io.DEFAULT_BUFFER_SIZE,以便更安全一些。然后我用我自己的函数重写了f.read,该函数结合了上述内容,在整个磁盘上透明地f.read。这样一来,f.read就可以按照你期望的方式工作了。

    Chibueze Opata
    Chibueze Opata
    发布于 2021-06-23
    0 人赞同

    你说的是这个片段对某一特定硬盘不起作用?你能告诉我们这个硬盘的细节,以及你如何知道它不正确。

    但是,可以尝试使用纯winapi的方法来代替。可以用 DeviceIoControl 来做这件事 舒适地 .见一 complete code listing in cpp.

    我知道有一种方法可以用Python写C++,所以祝你好运 :)

    Yeo
    这个片段对任何硬盘都有效,只是结果比HxD应用程序的结果要少。HxD检测的扇区比WinAPI检测的多。 最初,我用C语言来做 DeviceIoControl ,但结果也少。然后我又用Python尝试WMI,结果也少了。 我试着在另一台有不同磁盘的机器上运行,使用这个WinAPI的结果总是比HxD检测的少。
    据我所知,WINAPI应该提供最好的准确性。其他的可能性可能是你的磁盘不正常或者HxD是错误的。你能在这里公布你得到的不同的数值大小吗?
    Yeo
    我刚刚上传了问题更新2中的屏幕截图。你是对的,WINAPI总是提供最好的准确性。但在 Win32_DiskDrive ,有一个说明说。 The value may be inaccurate if the drive uses a translation scheme to support high-capacity disk sizes. 。我不太明白这个说明是什么意思。如何解决这个问题。为什么HxD可以检测到正确的值?
    你没有添加WINAPI的返回内容?
    Yeo
    Win32_DiskDrive返回给我所有关于 DiskDrive property .所以我只是访问它的属性(SectorSize)。对不起,如果我误解了,因为我不明白你说的WINAPI回报是什么意思
    wolfram
    wolfram
    发布于 2021-06-23
    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)