2009-03-04 16 views
23

Google me dio: http://developer.apple.com/samplecode/LoginItemsAE/index.htmlRegístrese como elemento de inicio de sesión con Cocoa?

Y pensé que debe haber una mejor manera que utilizar AppleScript Events.

Así que descargué las fuentes de Growl. Usan las fuentes exactas de ese artículo de desarrollador de Apple.

¿Hay una manera mejor?

(me refiero a inicio partidas de cuentas en Preferencias del sistema, es decir, hacer empezar mi programa cuando el usuario se conecta, mediante programación.)

+0

Un Google sin relación me hizo la siguiente documentación de Apple integral: http://developer.apple.com/documentation/MacOSX/Conceptual/BPSystemStartup/Articles/CustomLogin.html – mxcl

+0

Por cierto, he tenido ocasionalmente problemas con usando AppleEvents para obtener y configurar la lista de elementos de inicio de sesión, porque el servicio en segundo plano utilizado por AppleScript para esto (no recuerdo el nombre ahora) se colgó, y por lo tanto, mi aplicación también se colgaría al inicio cuando verificara si tenía que actualice su elemento de inicio de sesión después de que la aplicación haya sido renombrada o movida. Espero que la solución LSSharedFileList no sufra este problema, solo lo he usado recientemente, así que no tengo datos para respaldarlo, pero es probable que esto evite el problema a menos que internamente solo use AppleEvents. –

Respuesta

28

Hay una API que hay de nuevo en Leopard llamada LSSharedFileList. Una de las cosas que le permite hacer es ver y editar la lista de Elementos de inicio de sesión (llamados Elementos de inicio de sesión en esa API).

BTW, soy el desarrollador principal de Growl. Todavía no nos hemos alejado de AE ​​porque todavía necesitamos Tiger, pero estoy pensando en dejar eso para 1.2 (aún no lo he discutido con los otros desarrolladores). Cuando eliminemos Tiger, también eliminaremos LoginItemsAE y cambiaremos a la API de la Lista de archivos compartidos.


EDITAR a partir del año 2012: Desde 2009, cuando escribí originalmente esta respuesta, Growl ha cambiado a LSSharedFileList y he dejado el proyecto.

+2

Creo que te refieres a LSSharedFileList –

+0

¿Comprobaste cómo funciona en Lion? En ocasiones, las llamadas a LSSharedFileList * se bloquean (recibí una queja del usuario y vi un registro de bloqueo en la AppStore). Como Growl es usado por mucha gente, también deberías recibir sush logs, ¿no? Esto parece suceder cuando hay algunas unidades de red no montadas. –

+1

Uh, acabo de encontrar una respuesta: en LSSharedFileListItemResolve pase kLSSharedFileListDoNotMountVolumes como flags. Posiblemente, kLSSharedFileListNoUserInteraction debería ser necesario también. –

5

que hacen esto en un app I'm writing:

Salida UKLoginItemRegistry para una manera fácil de hacer esto de forma pragmática. Afaik, no hay forma de que Tiger haga esto sin Apple Events; en Leopard hay una mejor manera, pero si usas UKLoginItemRegistry realmente no hay problema. Aquí está el código completo de la aplicación de un elemento de menú "Abrir al iniciar sesión"

+ (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]; 
    } 
} 
+0

¿Se da cuenta el código si no tiene que usar AppleScript? –

+4

El código no se da cuenta de nada, solo son algunos bits en un disco. No entiendo lo que estás diciendo. –

+2

Creo que la pregunta de Alexsander es si UKLoginItemRegistry utiliza LSSharedFileList cuando está disponible. –

15

Me tropecé con LaunchAtLoginController de Ben Clark-Robinson. Una solución muy elegante a un problema muy común.

+2

esto es bastante agradable y fácil de usar, gracias. –

+1

Funciona muy bien. Probado en 10.6 y 10.7 – rydgaze

+3

Ese código no usa ARC y utiliza 'LSSharedFileListItemResolve', que está en desuso en OS X 10.10. Resolví estos problemas usando las sugerencias de Xcode para ARC y reemplazando 'LSSharedFileListItemResolve' con' CFURLRef currentItemURL = LSSharedFileListItemCopyResolvedURL (item, resolutionFlags, NULL) '. Ahora funciona sin advertencia para mí. – VinceFior

11

Esto funciona en 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; 
} 
+0

Indique en qué sistemas se ejecuta y no con qué versión IDE compiló el código, esta información es no vale la pena mencionarlo –

+3

Esto funciona perfectamente gracias. A partir de OSX 10.10 'LSSharedFileListItemResolve' está en desuso. En su lugar, use algo como: 'CFURLRef itemUrlRef = LSSharedFileListItemCopyResolvedURL (itemRef, 0, &err);' – CD1212

+0

No insertando mi aplicación en Elementos de inicio de sesión en Preferencias del Sistema. – ManiaChamp

Cuestiones relacionadas