Comment puis-je obtenir l'icône d'un périphérique de stockage sous Mac OS X?

StackOverflow https://stackoverflow.com/questions/580002

  •  06-09-2019
  •  | 
  •  

Question

J'ai trouvé mes appareils utilisant IOServiceGetMatchingServices et a obtenu le dictionnaire de la propriété comme ceci:

kernResult = IORegistryEntryCreateCFProperties(nextMedia,
                    (CFMutableDictionaryRef *)&props,
                                              kCFAllocatorDefault, 0);

A partir de ce dictionnaire, je peux extraire les informations pour les icônes:

NSString *bId = [props valueForKeyPath:@"IOMediaIcon.CFBundleIdentifier"];
NSString *rFile = [props valueForKeyPath:@"IOMediaIcon.IOBundleResourceFile"];

Ces deux me donnent ce (à titre d'exemple):

com.apple.iokit.IOStorageFamily   (Bundle identifier)
Internal.icns                     (Resource File)

J'ai essayé d'extraire l'icône en utilisant cette méthode:

NSBundle *bundleWithIcon = [NSBundle bundleWithIdentifier:bId];
NSString *iconPath = [bundleWithIcon pathForResource:rFile ofType:nil];

Mais bundleWithIcon est nil.

Est-ce même la bonne méthode pour obtenir l'icône?

Je pense que je dois en quelque sorte charger le paquet pour être en mesure de le charger avec bundleWithIdentifier, comment puis-je faire?

PS: Il y a une autre question qui (je pense) essaie de demander la même chose, mais ne demande que des paquets, pas si cela est la manière correcte.

Était-ce utile?

La solution 2

Tout récemment Andrew Myrick a répondu à une question similaire sur la liste de diffusion darwin-dev:

  

KextManagerCreateURLForBundleIdentifier()   en <IOKit/kext/KextManager.h> peut être   d'utilisation, mais je crois que cela fonctionne seulement   pour kexts qui sont soit 1) de chargement,   ou 2) en / S / L / E /. Voici la neige   Leopard HeaderDoc:

/*!
 * @function KextManagerCreateURLForBundleIdentifier
 * @abstract Create a URL locating a kext with a given bundle identifier.
 *
 * @param    allocator
 *           The allocator to use to allocate memory for the new object.
 *           Pass <code>NULL</code> or <code>kCFAllocatorDefault</code>
 *           to use the current default allocator.
 * @param    kextIdentifier
 *           The bundle identifier to look up.
 *
 * @result
 * A CFURLRef locating a kext with the requested bundle identifier.
 * Returns <code>NULL</code> if the kext cannot be found, or on error.
 *
 * @discussion
 * Kexts are looked up first by whether they are loaded, second by version.
 * Specifically, if <code>kextIdentifier</code> identifies a kext
 * that is currently loaded,
 * the returned URL will locate that kext if it's still present on disk.
 * If the requested kext is not loaded,
 * or if its bundle is not at the location it was originally loaded from,
 * the returned URL will locate the latest version of the desired kext,
 * if one can be found within the system extensions folder.
 * If no version of the kext can be found, <code>NULL</code> is returned.
 */
CFURLRef KextManagerCreateURLForBundleIdentifier(
    CFAllocatorRef allocator,
    CFStringRef    kextIdentifier);
     

Notez que avant Snow Leopard, il   peut seulement fonctionner pour kexts en / S / L / E; le   API existait, mais il n'y avait pas   HeaderDoc décrivant son comportement.

cela a fonctionné pour moi vraiment bien sur Mac OS X 10.5.

Autres conseils

Vous pouvez utiliser NSWorkspace.
L'image initiale est 32x32, mais il a des représentations pour les autres tailles et en conséquence l'échelle

NSWorkspace * ws = [NSWorkspace sharedWorkspace];
NSImage * icon = [ws iconForFile:@"/Volumes/Whatever"];
NSLog(@"%@", [icon representations]); // see what sizes the icon has
icon.size = NSMakeSize(512, 512);

cela peut vous aider. (Ou peut-être pas) ...

en jouant avec la commande « ioreg » je suis tombé sur quelque chose qui m'a rappelé de votre question, et je vais le poster:

essayez la commande suivante:

ioreg -c IOMedia -x

qui donnera un grand désordre de sortie qui ressemble à quelque chose comme ceci:

  |     +-o IOBlockStorageDriver  <class IOBlockStorageDriver, registered, matched, active, busy 0, retain 7>
  |       +-o Apple read/write Media  <class IOMedia, registered, matched, active, busy 0, retain 9>
  |         | {
  |         |   "Removable" = Yes
  |         |   "BSD Unit" = 0x4
  |         |   "IOBusyInterest" = "IOCommand is not serializable"
  |         |   "BSD Minor" = 0xc
  |         |   "Ejectable" = Yes
  |   |         |   "BSD Name" = "disk4"
  |         |   "Leaf" = No
  |         |   "IOMediaIcon" = {"CFBundleIdentifier"="com.apple.iokit.IOStorageFamily","IOBundleResourceFile"="Removable.icns"}
  |         |   "Preferred Block Size" = 0x200
  |         |   "Whole" = Yes
  |         |   "Open" = Yes
  |         |   "Size" = 0x100000
  |         |   "Writable" = Yes
  |         |   "Content" = "Apple_partition_scheme"
  |         |   "IOGeneralInterest" = "IOCommand is not serializable"
  |         |   "Content Hint" = ""
  |         | }         |   "BSD Major" = 0xe

tout cela me porte à croire (et donc ici recommander aveuglément que vous enquêtez) que si vous traversez la mise en correspondance d'arborescence du registre io contre « IOMEDIA », vous pouvez obtenir des dictionnaires de propriété qui contiendra une entrée calée « IOMediaIcon », qui apparaît lui-même être une collection pour vous informer d'un identificateur de paquet et un nom de fichier de ressources.

ne veut pas dire que cela est facile ... mais regardez dans le SDK FireWire pour tout le code exemple, vous devrez peut-être ... en tout cas, il est probablement « meilleure » que codage en dur des chemins pré-remplies (qui pourraient disparaître dans les prochaines versions du système d'exploitation).

| K <

  

Ces deux me donnent ce (à titre d'exemple):

     

com.apple.iokit.IOStorageFamily (identificateur Bundle)     Internal.icns (fichier de ressources)

     

J'ai essayé d'extraire l'icône en utilisant cette méthode:

     

* NSBundle bundleWithIcon = [NSBundle bundleWithIdentifier: Bid];     NSString * ICONPATH = [bundleWithIcon pathForResource: RFILE ofType: nil];

     

Mais bundleWithIcon est nil.

bundleWithIdentifier: vous oblige à avoir créé une instance NSBundle pour un faisceau avec cet identifiant; il semble que une instance créée précédemment. Par conséquent, vous aurez besoin de trouver le paquet dans le système de fichiers et instancier par chemin. , Vous semblez heureusement avoir déjà le lien à la question à ce sujet.

Un volume sans une icône personnalisée va être affichée avec l'une des icônes génériques du système d'exploitation que vous avez chemins difficiles ici avons écrit. Un volume avec une icône personnalisée va stocker cette icône sur son système de fichiers, et si ce n'est pas monté, il devient tout à fait trouver votre travail.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top