Cómo distinguir discos duros USB y SSD de llaves USB / pendrives en macOS
¿Cómo es posible que el código distinga entre discos duros USB externos y unidades de estado sólido, por un lado, frente a memorias USB, por otro lado?
No estoy familiarizado con las API de macOS (o llamadas al sistema, interrupciones, mensajes y otras cosas), pero supongo que estaría en el kit de E / S o en el arbitraje de disco.
En la línea de comandos de la Terminal, puede usar system_profiler SPUSBDataType
y ver esta información en la sección "Medios extraíbles".
Respuestas
Puede obtener la información extraíble / expulsable directamente de la URL, la expulsión es suficiente para la diferenciación
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)
}
Nunca antes había escrito código macOS o Swift. Aprendí lo suficiente para reunir esta prueba de concepto. Solo hace la generalización bidireccional como en mi pregunta: medios extraíbles y / o expulsables frente a medios no extraíbles no expulsables. Los DMG se agrupan con memorias USB y tarjetas SD. Los discos ópticos y los disquetes seguramente también lo son. No tengo idea de si existe un tipo de almacenamiento en el que solo uno de "extraíble" y "eyectable" es verdadero, pero no ambos ...
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")
}
}
}