This depends heavily on what you mean by "has a graphical interface." Do you mean, "is displaying a window?" Or "has a dock icon?" Or "has access to the Aqua context such that it could display a window if it wanted to?" Or "is linked with AppKit?"
An app bundle that does not have a dock icon will have the Info.plist
key LSUIElement
set to "1". You can fetch this using CFBundleGetValueForInfoDictionaryKey()
(or the NSBundle
equivalent if you're in Objective-C). This does not mean the application has no GUI, but does mean it won't show up in the dock. Many LSUIElement
apps have a status item UI.
You can also check that you actually have an Info.plist
at all using CFBundleCopyBundleURL()
or the like. If you don't have an Info.plist
, then you're not going to be a "GUI-like" program in all likelihood. (Though again, it's possible to generate GUIs without this).
You can use weak linking to test for AppKit:
if (NSApplicationMain != NULL) {
// We're linked with AppKit
}
That's a fairly good indicator that you're going to have a UI. But it won't catch older Carbon apps.
Some more background on what you mean by "I am inside the process" would be helpful. I assume you're a framework and want to behave differently for GUI apps than for non-GUI apps?
To detect an application capable of drawing on the screen, I would check for whether CoreGraphics
is linked. That'll only work for programs built since 10.3, but should be fairly accurate (I believe that old QuickDraw apps still link Core Graphics in 10.3+, but I don't have one handy to check). Probably the best way is to do a weak linking check against CGColorCreate()
since it's been around for a long time and is unlikely to ever go away:
extern CGColorRef CGColorCreate(CGColorSpaceRef space, const CGFloat components[])
__attribute__((weak_import));
...
if (CGColorCreate != NULL) {
// Linked with CoreGraphics. Probably a GUI
Of course things can link with CoreGraphics and be capable of drawing on the screen, but never actually draw on the screen. They might link with CoreGraphics in order to do image processing. It might be more accurate by looking for ApplicationServices
. You could test ApplicationServicesVersionNumber
against NULL
, but that's not documented.
This will not catch X apps, since they don't technically draw on the screen. They send commands to X11.app, which is a GUI. Do you consider /usr/X11/bin/xterm a GUI for this purpose? /usr/X11/bin/xeyes?
There is no particular flag I'm aware of in any app that says unambiguously "I draw on the screen." Drawing on the screen is not something you need to pre-declare. Apps that draw on the screen don't have to do so every time they run. Apps that are generally invisible might optionally or occasionally create a status item. It's hard to come up with a single description that includes GrowlHelperApp.app, Pages.app, and /usr/X11/bin/xeyes.