注册为cocoalogin项目?

Google给了我: http : //developer.apple.com/samplecode/LoginItemsAE/index.html

我觉得必须有比使用AppleScript事件更好的方法。

所以我下载了咆哮声源。 他们使用苹果开发人员文章的确切来源。

有没有更好的办法?

(我指的是“系统偏好设置”中的“帐户中的login项目”,即,在用户login时以编程方式启动我的程序)

Leopard中有一个名为LSSharedFileList的API。 它允许你做的事情之一是查看和编辑login项目列表(在该API中称为会话login项目)。

顺便说一下,我是Growl的首席开发人员。 我们还没有离开AE,因为我们仍然需要Tiger,但是我正在考虑把它放到1.2(还没有和其他开发者讨论过)。 当我们放弃Tiger时,我们也会放弃LoginItemsAE,并切换到共享文件列表API。


编辑从2012年:自2009年,当我最初写这个答案,咆哮已经切换到LSSharedFileList,我已经离开了项目。

我偶然发现了Ben Clark-Robinson的LaunchAtLoginController 。 一个非常普遍的问题非常优雅的解决scheme。

这适用于xcode 5。

 - (BOOL)isLaunchAtStartup { // See if the app is currently in LoginItems. LSSharedFileListItemRef itemRef = [self itemRefInLoginItems]; // Store away that boolean. BOOL isInList = itemRef != nil; // Release the reference if it exists. if (itemRef != nil) CFRelease(itemRef); return isInList; } - (void)toggleLaunchAtStartup { // Toggle the state. BOOL shouldBeToggled = ![self isLaunchAtStartup]; // Get the LoginItems list. LSSharedFileListRef loginItemsRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); if (loginItemsRef == nil) return; if (shouldBeToggled) { // Add the app to the LoginItems list. CFURLRef appUrl = (__bridge CFURLRef)[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]; LSSharedFileListItemRef itemRef = LSSharedFileListInsertItemURL(loginItemsRef, kLSSharedFileListItemLast, NULL, NULL, appUrl, NULL, NULL); if (itemRef) CFRelease(itemRef); } else { // Remove the app from the LoginItems list. LSSharedFileListItemRef itemRef = [self itemRefInLoginItems]; LSSharedFileListItemRemove(loginItemsRef,itemRef); if (itemRef != nil) CFRelease(itemRef); } CFRelease(loginItemsRef); } - (LSSharedFileListItemRef)itemRefInLoginItems { LSSharedFileListItemRef res = nil; // Get the app's URL. NSURL *bundleURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]; // Get the LoginItems list. LSSharedFileListRef loginItemsRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); if (loginItemsRef == nil) return nil; // Iterate over the LoginItems. NSArray *loginItems = (__bridge NSArray *)LSSharedFileListCopySnapshot(loginItemsRef, nil); for (id item in loginItems) { LSSharedFileListItemRef itemRef = (__bridge LSSharedFileListItemRef)(item); CFURLRef itemURLRef; if (LSSharedFileListItemResolve(itemRef, 0, &itemURLRef, NULL) == noErr) { // Again, use toll-free bridging. NSURL *itemURL = (__bridge NSURL *)itemURLRef; if ([itemURL isEqual:bundleURL]) { res = itemRef; break; } } } // Retain the LoginItem reference. if (res != nil) CFRetain(res); CFRelease(loginItemsRef); CFRelease((__bridge CFTypeRef)(loginItems)); return res; } 

我在我正在写的应用程序中执行此操作:

查看UKLoginItemRegistry是一个简单的方法来做到这一点务实。 Afaik,没有苹果事件,Tiger没有办法做到这一点; 在Leopard中有更好的方法,但是如果使用UKLoginItemRegistry,那真的没有问题。 以下是实现“login时打开”菜单项的完整代码

 + (bool)isAppSetToRunAtLogon { int ret = [UKLoginItemRegistry indexForLoginItemWithPath:[[NSBundle mainBundle] bundlePath]]; NSLog(@"login item index = %i", ret); return (ret >= 0); } - (IBAction)toggleOpenAtLogon:(id)sender { if ([PopupController isAppSetToRunAtLogon]) { [UKLoginItemRegistry removeLoginItemWithPath:[[NSBundle mainBundle] bundlePath]]; } else { [UKLoginItemRegistry addLoginItemWithPath:[[NSBundle mainBundle] bundlePath] hideIt: NO]; } } 

我已经重构了一些答案,在NSApplication上提供了一个launchAtLogin属性。

https://gist.github.com/joerick/73670eba228c177bceb3

在这里查看一个开源的例子: https : //github.com/invariant/rhpnotifier (LoginItem.m,LoginItem.h)