2009-03-04 11 views
23

Google mi ha dato: http://developer.apple.com/samplecode/LoginItemsAE/index.htmlRegistrati come elemento di accesso con Cocoa?

E ho pensato che ci deve essere un modo migliore di utilizzare AppleScript Events.

Così ho scaricato i sorgenti di Growl. Usano le fonti esatte di questo articolo degli sviluppatori Apple.

C'è un modo migliore?

(mi riferisco alla Login I prodotti in Account in Preferenze di Sistema, cioè facendo iniziare il mio programma quando l'utente accede, a livello di codice.)

+0

Un estraneo Google mi ha fatto la seguente documentazione di Apple completa: http://developer.apple.com/documentation/MacOSX/Conceptual/BPSystemStartup/Articles/CustomLogin.html – mxcl

+0

BTW, ho avuto occasionalmente problemi con utilizzando AppleEvents per ottenere e impostare l'elenco degli elementi di accesso, perché il servizio in background utilizzato da AppleScript per questo (non richiamare il nome adesso) è stato bloccato, e quindi la mia app si bloccava all'avvio quando controllava se doveva aggiorna il suo elemento di accesso dopo che l'app potrebbe essere stata rinominata o spostata. Spero che la soluzione LSSharedFileList non soffra di questo problema: l'ho utilizzato solo di recente, quindi non ho ancora dati per eseguire il backup, ma è probabile che questo eviti il ​​problema a meno che non utilizzi internamente solo AppleEvents). –

risposta

28

C'è un'API che c'è di nuovo in Leopard chiamato LSSharedFileList. Una delle cose che ti permette di fare è visualizzare e modificare l'elenco degli elementi di login (chiamati elementi di login della sessione in quell'API).

BTW, sono lo sviluppatore principale di Growl. Non siamo ancora passati da AE perché abbiamo ancora bisogno di Tiger, ma sto pensando di lasciarlo per 1.2 (non ho ancora parlato con gli altri sviluppatori). Quando rilasciamo Tiger, rilasciamo anche LoginItemsAE e passiamo all'API dell'elenco file condiviso.


EDIT dall'anno 2012: Dal 2009, quando ho originariamente scritto questa risposta, Growl è passato a LSSharedFileList e ho abbandonato il progetto.

+2

Penso tu intenda LSSharedFileList –

+0

Hai controllato come funziona in Lion? A volte le chiamate LSSharedFileList * si bloccano (ho ricevuto un reclamo da parte dell'utente e ho visto il registro degli arresti anomali in AppStore). Poiché Growl è utilizzato da molto ppl, dovresti anche ricevere i log sush, come sei? Questo sembra accadere quando ci sono alcune unità di rete non montate. –

+1

Uh, ho appena trovato una risposta - in LSSharedFileListItemResolve passiamo kLSSharedFileListDoNotMountVolumes come flag. Potrebbe anche essere necessario kLSSharedFileListNoUserInteraction. –

5

faccio questo in un app I'm writing:

Partenza UKLoginItemRegistry per un un modo semplice per farlo in modo pragmatico. Afaik, in Tiger non c'è modo di farlo senza Apple Events; in Leopard c'è un modo migliore, ma se usi UKLoginItemRegistry non è un problema. Ecco il codice completo per l'attuazione di un "Open all'accesso" voce di menu

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

Il codice si rende conto se non deve utilizzare AppleScript? –

+4

Il codice non realizza nulla, sono solo alcuni bit su un disco. Non capisco cosa stai dicendo. –

+2

Credo che la domanda di Alexsander sia se UKLoginItemRegistry utilizzi LSSharedFileList quando è disponibile. –

15

Mi sono imbattuto in Ben Clark-Robinson LaunchAtLoginController. Una soluzione molto elegante per un problema molto comune.

+2

questo è abbastanza bello e semplice da usare, grazie. –

+1

Funziona alla grande. Testato in 10.6 e 10.7 – rydgaze

+3

Quel codice non usa ARC e usa 'LSSharedFileListItemResolve', che è deprecato in OS X 10.10. Ho risolto questi problemi utilizzando i suggerimenti di Xcode per ARC e sostituendo 'LSSharedFileListItemResolve' con' CFURLRef currentItemURL = LSSharedFileListItemCopyResolvedURL (item, resolutionFlags, NULL) '. Ora funziona senza preavviso per me. – VinceFior

11

Questo funziona su 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

Per favore dicci quali sistemi su cui gira e non con quale versione IDE hai compilato il codice, questa informazione è non vale la pena menzionare. –

+3

Funziona perfettamente grazie. A partire da OSX 10.10 'LSSharedFileListItemResolve' è deprecato. Utilizzare invece qualcosa sulla falsariga di: 'CFURLRef itemUrlRef = LSSharedFileListItemCopyResolvedURL (itemRef, 0, &err);' – CD1212

+0

Non inserisce la mia applicazione negli elementi di login in Preferenze di Sistema. – ManiaChamp

Problemi correlati