【问题标题】:How to distinguish USB hard drives and SSDs from USB keys / pen drives on macOS如何在 macOS 上区分 USB 硬盘和 SSD 与 USB 密钥/笔式驱动器
【发布时间】:2021-03-22 11:53:20
【问题描述】:

一方面,代码如何区分外部 USB 硬盘驱动器和固态驱动器与另一方面的 USB 记忆棒?

我不熟悉 macOS API(或系统调用、中断、消息传递和其他东西),但我猜它会在 I/O Kit 或磁盘仲裁中使用?

在终端命令行上,您可以使用system_profiler SPUSBDataType 并查看“可移动媒体”下列出的此信息。

【问题讨论】:

  • 任何通过 USB 连接的驱动器(笔/硬盘/ssd)都将被视为仅可移动驱动器。您可以尝试的一件事是检查它们的大小和格式类型。但我认为这对你正在寻找的东西没有多大帮助。
  • @AjayKumar:似乎有“可移动媒体”的概念。当我在 USB 读卡器中连接 USB 硬盘驱动器、USB SSD、USB 记忆棒和 SD 卡时,system_profiler SPUSBDataType 认为 USB 记忆棒和 SD 卡是“可移动媒体”,而不是硬盘驱动器或 SSD,即使也可以卸下整个驱动器。我猜这是需要将软盘、CD 和 DVD 驱动器与硬盘驱动器区分开来的扩展。我使用跨平台库遇到了这个问题,该库从 Windows 的磁盘列表中排除了 USB 记忆棒,但对于 Mac 没有。
  • 嗯。有趣的东西。我已经为这个线程添加了书签。继续挖掘。祝你好运。 !
  • 通常,除了系统调用、中断、消息传递和使用 C 时涉及的其他事情之外,根本没有 API。您可以通过系统调用以编程方式查找设备。 system_profiler 听起来像是一个程序,而不是系统接口。

标签: macos usb-drive iokit usb-mass-storage diskarbitration


【解决方案1】:

可以直接从URL获取可移除/可弹出信息,可弹出就足以区分

let mountedVolumeURLs = FileManager.default.mountedVolumeURLs(includingResourceValuesForKeys: [.nameKey, .volumeIsEjectableKey])!
for volumeURL in mountedVolumeURLs where volumeURL.path == "/" || volumeURL.path.hasPrefix("/Volumes") {
    let resources = try! volumeURL.resourceValues(forKeys: [.nameKey, .volumeIsEjectableKey])
    
    let ejectable = resources.volumeIsEjectable!
    let name = resources.name!
    
    var type = name + " is "
    type += ejectable ? "USB stick, SD card, etc" : "hard drive, SSD, etc";
    type += " ("
    type += ejectable ? "" : "not "
    type += "ejectable)"
    print(" ", type)
}

【讨论】:

  • 太棒了!有没有一种简单的方法可以打印出所有的键/值对?我想找到过滤掉不是真正驱动器的“家庭”和“网络”的标准。到目前为止,我太新手了,无法通过浏览文档和谷歌搜索来弄清楚如何......
  • 请看编辑,卷是启动卷(/)和/Volumes中的所有卷
  • 事实证明,这只是检查路径是否以/Volumes开头是不可靠的:apple.stackexchange.com/questions/409482/…
  • 当然,基本上可以将磁盘挂载到其他地方,但可能性很小,我不知道任何情况。您在 Stackexchange 上接受的答案与 shared 卷有关,但这个问题明确与 local USB 连接的硬盘有关。
【解决方案2】:

我以前从未编写过 macOS 或 Swift 代码。我学到的东西刚好够把这个概念证明放在一起。它只会像我的问题那样进行双向概括:可移动和/或可弹出媒体与不可移动不可弹出媒体。 DMG 与 U 盘和 SD 卡混为一谈。光盘和软盘当然也是。我不知道是否存在存储类型之类的东西,其中只有“可移动”和“可弹出”之一为真,但不是两者都为真......

import Cocoa
import DiskArbitration

if let session = DASessionCreate(kCFAllocatorDefault) {
    let mountedVolumeURLs = FileManager.default.mountedVolumeURLs(includingResourceValuesForKeys: nil)!
    for volumeURL in mountedVolumeURLs {
        if let disk = DADiskCreateFromVolumePath(kCFAllocatorDefault, session, volumeURL as CFURL),
            let bsdName = DADiskGetBSDName(disk) {
            let bsdString = String(cString : bsdName)
            print(volumeURL.path, bsdString)
            
            if let descDict = DADiskCopyDescription(disk) as? [String: CFTypeRef] {
                let removable : Bool, ejectable : Bool
                if let val = descDict["DAMediaRemovable"] as? Bool {
                    removable = val
                    if let val = descDict["DAMediaEjectable"] as? Bool {
                        ejectable = val

                        var type = ""
                        
                        type += removable || ejectable ? "USB stick, SD card, etc" : "hard drive, SSD, etc";
                        
                        type += " ("
                        
                        type += removable ? "" : "not "
                        type += "removable"
                        type += ", "
                        type += ejectable ? "" : "not "
                        type += "ejectable"
                        
                        type += ")"

                        print(" ", type)
                    }
                }
            }
            print("\n")
        }
    }
}

【讨论】:

  • 我们如何获取所有卷 url,例如 C++ 中的“mountedVolumeURLs”。
  • @AhadKhan:我不知道。我宁愿用 C/C++ 编写代码,但要弄清楚如何在 macOS 中做任何事情是一场战斗。我已经转移到其他事情上,现在忘记了关于这些事情的一切。祝你好运!
猜你喜欢
  • 2011-03-24
  • 1970-01-01
  • 2013-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多