Is there any way of telling whether a Cocoa application has been launched as a log item rather than by double clicking it?
6 Answers
When an application is launched without a document to open or print, it receives an 'oapp' (a.k.a. kAEOpenApplication) Apple Event. That event may have a property data (keyAEPropData) parameter. For an ordinary launch, that parameter is absent or 0. For a launch from a login item, it's keyAELaunchedAsLogInItem. (When your app is launched to provide a service, it's keyAELaunchedAsServiceItem.)
You can check for this with the following code in your -applicationWill/DidFinishLaunching: method:
NSAppleEventDescriptor* event = [[NSAppleEventManager sharedAppleEventManager] currentAppleEvent];
if ([event eventID] == kAEOpenApplication &&
[[event paramDescriptorForKeyword:keyAEPropData] enumCodeValue] == keyAELaunchedAsLogInItem)
{
// you were launched as a login item
}
Swift 3:
let event = NSAppleEventManager.shared().currentAppleEvent
let launchedAsLogInItem =
event?.eventID == kAEOpenApplication &&
event?.paramDescriptor(forKeyword: keyAEPropData)?.enumCodeValue == keyAELaunchedAsLogInItem
- 964
- 8
- 21
- 88,520
- 7
- 116
- 154
-
the link is dead now :( – Michael Jan 27 '15 at 09:49
-
Tons of stuff in Apple's legacy documentation area is broken. They don't seem to care. – Ken Thomases Jan 27 '15 at 10:10
-
@Michael: OK, I've edited it with a link that's working for me. – Ken Thomases Jan 27 '15 at 10:13
-
thanks. BTW, the code still works now (early 2015) - this is far from normal for apple APIs ;) – Michael Jan 27 '15 at 10:46
-
Does not work on macOS 12 Monterey, when started by ServiceManagement.framework. – Tom Mar 16 '22 at 19:42
-
Couldn't get this to work on Ventura either. There's no Apple event in both cases (when starting as a normal item and as a launch item). – Niels Mouthaan Oct 27 '22 at 19:55
-
Note that the check above *DOES* work for me on macOS 13.3 Ventura in my SwiftUI app using the ServiceManagement.framework to add a start at login item. I run the check in `applicationDidFinishLaunching` of the `NSApplicationDelegateAdaptor` I have setup. – Mac_Cain13 Apr 05 '23 at 18:40
The Chromium project has some code to do this. Follows the approach spelled out here, checking the parent process and the login item list.
- 4,156
- 2
- 34
- 48
-
1For those too lazy to look up the code, it involves calling `ProcessInformationCopyDictionary` first on the current process to find the parent, and then on the parent process to find out whether it is the login window process. – JWWalker Jan 22 '13 at 22:59
-
It also shows how to look up the app in the startup items list to see if it was marked as "start hidden". – J. Perkins Jan 23 '13 at 14:34
As far i'm aware there is no proper way to check this, but there are some thoughts:
Best solution:
Create two different applications, for example TheApp and TheAppLauncher.
Add TheApp to the applications folder and TheAppLaucher to the startup items.
Simply launch TheApp with a specific flag when TheAppLauncher is launched.
I hope this is clear :)
Other 'ugly' option:
Check whether the application is actually listed in the login items:
https://github.com/carpeaqua/Shared-File-List-Example/
Make the application log the exact time it launched.
Then compare it with the last time the user logged-in.
The finger command provides this information (use NSTask).
Good change it's launched as log-in item when the difference is small.
But yes, this is not completely reliable :)
- 26,765
- 9
- 65
- 71
Depending on exactly what you're doing, NSApplicationLaunchIsDefaultLaunchKey may be useful here. This is a key included in the NSNotification sent to applicationDidFinishLaunching:. From the documentation:
The value for this key is an NSNumber containing a Boolean value. The value is NO if the application was launched to open or print a file, to perform a Service action, if the application had saved state that will be restored, or if the application launch was in some other sense not a default launch. Otherwise its value will be YES.
In addition to the cases mentioned, it is also set to NO if the app is automatically launched on login. So if you're deciding whether to show some interface element, for example, this may be enough information to do what you're after.
Checking [[NSApplication sharedApplication] isHidden] may also be useful if you want to know whether the app was launched with the "hide" box checked.
Edit: On further testing, I'm not sure this is actually true. When the app is opened normally, NSApplicationLaunchIsDefaultLaunchKey is usually YES. When it's launched automatically, it seems to usually be NO, in the testing I've done so far. But neither is always true, so it seems this key may not be useful after all.
- 2,732
- 2
- 28
- 50
-
Hi,thanks for the tip. I've researched this a bit online, but while it should work, it seems to be bug invested. Somebody already opened a radar on it.. shame; you'd think they'd support that by now. – Frank R. Sep 12 '12 at 12:44
Maybe you could start the application with an option if started as a login item. For example call it MyApp.app --startupItem when used as a startup item and call it without that option when it is launched regularly.
The command line options can be check the classic C way, as they are passed to the main function as arguments.
- 5,007
- 1
- 39
- 56
-
My solution is different from Anne's as you only need one application only. – GorillaPatch Apr 06 '11 at 14:28
-
3I agree, your solution is better in developer perspective. But, for the user experience, you better use the launcher method. The average user can add applications to the login-tems, but they can't use additional options like you mention. To make it even more user friendly: Check if TheApp is listed in the log-in items, if yes, replace it by TheAppLauncher. This way the user can add both TheApp and TheAppLaunch with the same result. – Anne Apr 06 '11 at 19:15
-
Good point Anne. It starts getting interesting. My next idea was to have a look at the parent process but this is launchd for both cases. To be honest I have not had a look in Apple's docs about this problem, so maybe I am missing something. – GorillaPatch Apr 06 '11 at 19:59
-
Thanks guys. In the past, I put applications into the login items programmatically but that is quite dangerous because it's undocumented. It caused a lot of hassle when Tiger came out and the program would add itself every time it was launched slowly filing up the launch items dialog.. for that reason I don't want to go down the argument passing avenue, even though that's probably the cleanest solution overall. The "finger" idea is actually quite good and not too hard to implement.. funny thing is that you can specify "hide" as an option in the login items but I can't see how this is passed.. – Frank R. Apr 08 '11 at 10:15
Set up the login item so that "Hide" is checked then whenever your app is launched (awakeFromNib or init) check if the app is hidden or not.
- 1,641
- 16
- 21
-
1@Raffael For setting it to hide on launch see [here](https://github.com/inket/Next/blob/master/Next/LoginItem.m#L14-L43), and use [NSApp isHidden] for knowing if the app is hidden or not. – inket Mar 09 '15 at 09:02