按标识符定位包

Rhy*_*man 6 macos cocoa

我想从任意包标识符创建一个包,
例如com.apple.iokit.IOStorageFamily

这不是一个不合理的事情,因为bundle ID应该
是唯一的,但明显的代码不起作用:

NSString* bID = @"com.apple.iokit.IOStorageFamily";
NSBundle* bundle = [NSBundle bundleWithIdentifier:bID];
Run Code Online (Sandbox Code Playgroud)

此代码仅适用于您已加载的包
(问号,鸡和鸡蛋问题),事实上, 在您可以执行任何操作之前,您必须
了解比标识符更多的信息
.对于上面的ID样式,
我将最终组件转出并转换为其
/System/Library/Extensions/IOStorageFamily.kext
然后按路径加载.

这是最先进的技术还是有更普遍的方式?

Dav*_*wer 9

用这个

NSString *path = [[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier:@"com.apple.TextEdit"];
Run Code Online (Sandbox Code Playgroud)


小智 5

我认为 Mac OS X 不会在任何地方保存所有捆绑包 ID 的全局数据库。

如前所述,您可以使用 NSWorkspace 以非常简单的方式找到应用程序。

另外,由于您在示例中使用了 kext,因此在 Leopard (10.5) 上,有一个名为“kextfind”的工具,您可以运行它来在系统扩展文件夹中搜索 kext(除非您指向其他位置的 kext,否则不会找到)其他地方的工具)。kextfind 有很多选项——请参阅手册页了解详细信息——但是要通过捆绑包 ID 查找 kext,您可以执行以下操作:

kextfind -bundle-id com.apple.iokit.IOStorageFamily
Run Code Online (Sandbox Code Playgroud)

我们目前没有用于通过捆绑 ID 查找 kext 的 C 级 API。

至于从捆绑 ID 的最后一个组件破解路径:不要这样做。没有任何要求包装器名称与捆绑包 ID 的最后一个组件相匹配,而且我见过 kext(更不用说其他捆绑包了),其中两者不匹配。


Geo*_*lly 3

就在最近, Andrew Myrick在 darwin-dev 邮件列表上回答了类似的问题:

KextManagerCreateURLForBundleIdentifier() in<IOKit/kext/KextManager.h>可能有用,但我相信它只适用于 1) 加载或 2) 在 /S/L/E/ 中的 kext。这是雪豹标头文档:

/*!
 * @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);
Run Code Online (Sandbox Code Playgroud)

请注意,在 Snow Leopard 之前,它可能仅适用于 /S/L/E 中的 kext;API 存在,但没有描述其行为的 headerdoc。

对我来说,这在 Mac OS X 10.5 上运行得非常好。