Cara membedakan hard drive USB dan SSD dari kunci USB / drive pena di macOS

Dec 11 2020

Bagaimana mungkin kode membedakan antara hard drive USB eksternal dan solid-state drive di satu sisi dengan stik USB di sisi lain?

Saya tidak terbiasa dengan macOS API (atau panggilan sistem, interupsi, perpesanan, dan hal-hal lain) tetapi saya menduga itu ada di I / O Kit atau Disk Arbitration?

Pada baris perintah Terminal Anda dapat menggunakan system_profiler SPUSBDataTypedan melihat informasi ini terdaftar di bawah "Media Yang Dapat Dilepas".

Jawaban

2 vadian Dec 15 2020 at 15:19

Anda bisa mendapatkan informasi yang dapat dilepas / dikeluarkan langsung dari URL, yang dapat dikeluarkan sudah cukup untuk diferensiasinya

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)
}
1 hippietrail Dec 14 2020 at 19:19

Saya belum pernah menulis kode macOS atau Swift sebelumnya. Saya belajar cukup untuk mengumpulkan bukti konsep ini. Itu hanya membuat generalisasi dua arah seperti dalam pertanyaan saya: Media yang dapat dilepas dan / atau yang dapat dikeluarkan vs media yang tidak dapat dikeluarkan yang tidak dapat dikeluarkan. DMG disatukan dengan stik USB dan kartu SD. Disket optik dan pasti juga begitu. Saya tidak tahu apakah ada yang namanya jenis penyimpanan yang hanya satu dari "removable" dan "ejectable" yang benar tetapi tidak keduanya ...

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")
        }
    }
}