我正在编写首选项编辑器工具(请参阅http://www.tempel.org/PrefsEditor)。它实际上是defaults
命令的GUI版本。
我无法阅读(更不用说写)随机沙盒应用程序的首选项了。
例如,当我尝试获取Maps应用程序的键时,我返回NULL:
CFArrayRef prefs = CFPreferencesCopyKeyList (CFSTR("com.apple.Maps"), kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
但是,defaults
命令能够读取这些首字母:
defaults read com.apple.Maps
我想知道defaults命令如何实现这一点,尝试在我的工具中执行相同操作。
答案 0 :(得分:4)
试试:
CFPropertyListRef prop = CFPreferencesCopyValue(CFSTR("ElementsVersion"),
CFSTR("/Users/karsten/Library/Containers/com.apple.Maps/Data/Library/Preferences/com.apple.Maps"),
CFSTR("kCFPreferencesCurrentUser"),
CFSTR("kCFPreferencesAnyHost"));
似乎你需要文件的路径,而不仅仅是bundle-id
答案 1 :(得分:4)
Karsten的回答是正确的,但为了完整起见,defaults
命令使用未记录的_CFPreferencesCopyApplicationMap()
函数来检索首选项的完整URL。
#import <CoreFoundation/CoreFoundation.h>
extern CFDictionaryRef _CFPreferencesCopyApplicationMap(CFStringRef userName, CFStringRef hostName);
int main(int argc, char *argv[])
{
@autoreleasepool
{
CFDictionaryRef applicationMap = _CFPreferencesCopyApplicationMap(kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
CFArrayRef urls = CFDictionaryGetValue(applicationMap, CFSTR("com.apple.mail"));
CFShow(urls);
CFRelease(applicationMap);
}
}
答案 2 :(得分:1)
我已经在0xced的出色答案中添加了代码,以便可以将代码打包到接受捆绑ID作为参数的命令行工具中。如果这对有经验的Mac程序员来说是显而易见的,请原谅我,但是作为从未使用过CoreFoundation的人,我发现这并不简单。
#import <CoreFoundation/CoreFoundation.h>
extern CFDictionaryRef _CFPreferencesCopyApplicationMap(CFStringRef userName, CFStringRef hostName);
int main(int argc, char *argv[]) {
@autoreleasepool {
if (argc < 2) {
// Print usage string & exit.
fprintf(stderr, "usage: GetPrefDomains bundle_id\n");
exit(1);
}
// Get the bundle ID from the first command-line argument.
CFStringRef bundleID = CFStringCreateWithCString(NULL, argv[1], kCFStringEncodingUTF8);
// Get the list of preference domain urls.
CFDictionaryRef applicationMap = _CFPreferencesCopyApplicationMap(kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
CFArrayRef urls = CFDictionaryGetValue(applicationMap, bundleID);
// If no urls exist (invalid bundle ID), exit.
if (!urls) {
fprintf(stderr, "No preference domains found.\n");
exit(0);
}
// Print the paths to the preference domains.
CFIndex urlsCount = CFArrayGetCount(urls);
for (int i = 0; i < urlsCount; i++) {
CFURLRef url = CFArrayGetValueAtIndex(urls, i);
CFStringRef path = CFURLCopyPath(url);
printf("%s\n", CFStringGetCStringPtr(path, kCFStringEncodingUTF8));
}
// Clean up.
CFRelease(bundleID);
CFRelease(applicationMap);
}
}
将代码另存为GetPrefDomains.m,编译并调用为:
GetPrefDomains com.apple.mail
这对我很有用,因为令人惊讶的是defaults
命令区分大小写,并且在Mojave 10.14或更高版本(Safari&Mail,最著名)上受SIP文件系统保护的某些Apple应用程序无声地表现。再加上苹果的大小写规则不一致(com.apple.mail
与com.apple.Notes
),沙盒偏好路径以及文件系统不区分大小写和 的事实。您很快就会遇到一些非常令人沮丧的边缘情况。