简体   繁体   English

如何在 Mac OS X 中获取存储设备的图标?

[英]How can I get the icon for a storage device in Mac OS X?

I've found my devices using IOServiceGetMatchingServices and got the property dictionary like this:我使用IOServiceGetMatchingServices找到了我的设备并获得了如下属性字典:

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

From that dictionary I can extract the informations for the icons:从该字典中,我可以提取图标的信息:

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

Those two give me this (as an example):那两个给了我这个(例如):

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

I tried to extract the icon using this method:我尝试使用此方法提取图标:

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

But bundleWithIcon is nil .但是bundleWithIconnil

Is this even the correct method to get the icon?这甚至是获取图标的正确方法吗?

I think I have to somehow load the bundle to be able to load it with bundleWithIdentifier , how can I do this?我想我必须以某种方式加载捆绑包才能使用bundleWithIdentifier加载它,我该怎么做?

PS: There's another question which (I think) tries to ask the same thing, but only asks for bundles, not if this is the correct way. PS: 还有另一个问题(我认为)试图问同样的事情,但只要求捆绑,而不是如果这是正确的方法。

You could use NSWorkspace.你可以使用 NSWorkspace。
The initial image is 32x32, but it has representations for the other sizes and will scale accordingly初始图像为 32x32,但它具有其他尺寸的表示,并将相应地缩放

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

Just recently Andrew Myrick answered a similar question on the darwin-dev mailing list:就在最近, Andrew Myrick 在 darwin-dev 邮件列表上回答了一个类似的问题

KextManagerCreateURLForBundleIdentifier() in <IOKit/kext/KextManager.h> may be of use, though I believe it only works for kexts that are either 1) loaded, or 2) in /S/L/E/. <IOKit/kext/KextManager.h>中的KextManagerCreateURLForBundleIdentifier()可能有用,但我相信它仅适用于 1) 已加载或 2) 在 /S/L/E/ 中的 kext。 Here is the Snow 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);

Note that prior to Snow Leopard, it may only work for kexts in /S/L/E;请注意,在 Snow Leopard 之前,它可能仅适用于 /S/L/E 中的 kext; the API existed, but there was no headerdoc describing its behavior. API 存在,但没有描述其行为的标题文档。

For me this worked really well on Mac OS X 10.5.对我来说,这在 Mac OS X 10.5 上运行得非常好。

this may help you.这可能会对您有所帮助。 (or maybe not)... (或者可能不是)...

in playing around with the 'ioreg' command i came across something that reminded me of your question, and so I'll post it:在玩'ioreg'命令时,我遇到了一些让我想起你的问题的东西,所以我会发布它:

try issuing the following command:尝试发出以下命令:

ioreg -c IOMedia -x

which will yield a big mess of output which looks something like this:这将产生一大堆 output 看起来像这样:

  |     +-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

this all leads me to believe (and thus here blindly recommend that you investigate) that if you traverse the io registry tree matching against 'IOMedia' you can get property dictionaries that will contain an entry keyed "IOMediaIcon," which itself appears to be a collection informing you of a bundle identifier and a resource file name.这一切让我相信(因此这里盲目地建议您进行调查)如果您遍历与“IOMedia”匹配的 io 注册表树,您可以获得包含键入“IOMediaIcon”的条目的属性字典,它本身似乎是集合通知您捆绑标识符和资源文件名。

not to say that this is easy... but look into the FireWire SDK for all the example code you may need... in any case it's probably "better" than hard-coding pre-filled paths (which might disappear in future OS releases).并不是说这很容易...但是请查看FireWire SDK以获取您可能需要的所有示例代码...无论如何,它可能比硬编码预填充路径“更好”(这可能会在未来的操作系统中消失发布)。

|K< |K<

A volume without a custom icon is going to be displayed with one of the OS's generic icons which you've hard-coded paths to here.没有自定义图标的卷将与您在此处硬编码路径的操作系统通用图标之一一起显示。 A volume with a custom icon is going to store that icon on its filesystem, and if it's not mounted, finding it becomes entirely your job.带有自定义图标的卷将该图标存储在其文件系统中,如果未安装,则查找它完全是您的工作。

Those two give me this (as an example):那两个给了我这个(例如):

com.apple.iokit.IOStorageFamily (Bundle identifier) Internal.icns (Resource File) com.apple.iokit.IOStorageFamily(捆绑标识符) Internal.icns(资源文件)

I tried to extract the icon using this method:我尝试使用此方法提取图标:

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

But bundleWithIcon is nil .但是bundleWithIconnil

bundleWithIdentifier: requires you to have already created an NSBundle instance for a bundle with that identifier; bundleWithIdentifier:要求您已经为具有该标识符的捆绑包创建了一个 NSBundle 实例; it only looks up a previously-created instance.它只查找以前创建的实例。 Therefore, you'll need to find the bundle in the file-system and instantiate it by pathname.因此,您需要在文件系统中找到捆绑包并通过路径名对其进行实例化。 Fortunately, you seem to already have the link to the question about that.幸运的是,您似乎已经获得了有关该问题的链接。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM