Как я могу определить, есть ли у процесса графический интерфейс в OSX? - PullRequest
2 голосов
/ 19 октября 2011

Есть ли в любом случае, мы можем определить, если процесс имеет пользовательский интерфейс?Все, что связано с рисованием на экране.

Я смотрел на этот вопрос , но он не дает правильного ответа.Я в процессе.Есть ли API, где я могу запросить, или какой-то метод?

РЕДАКТИРОВАТЬ: я внутри процесса, я делаю инъекцию кода.Я хочу вести себя не так, как в приложениях с графическим интерфейсом.Я не могу использовать CFBundleGetValueForInfoDictionaryKey () или NSApplicationMain, так как хочу, чтобы модуль впрыска был легким, и, следовательно, я не могу связываться с этими структурами.

1 Ответ

6 голосов
/ 19 октября 2011

Это сильно зависит от того, что вы подразумеваете под «имеет графический интерфейс».Вы имеете в виду "отображает окно?"Или "имеет значок док-станции?"Или "имеет доступ к контексту Aqua, чтобы он мог отображать окно, если бы захотел?"Или «связан с AppKit?»

Пакет приложения, на котором нет значка закрепления, будет иметь для клавиши Info.plist key LSUIElement значение «1».Вы можете получить это, используя CFBundleGetValueForInfoDictionaryKey() (или NSBundle эквивалент, если вы находитесь в Objective-C).Это не означает, что приложение не имеет графического интерфейса, но означает, что оно не будет отображаться в доке.Многие LSUIElement приложения имеют пользовательский интерфейс элемента состояния.

Вы также можете проверить, действительно ли у вас есть Info.plist, используя CFBundleCopyBundleURL() или подобное.Если у вас нет Info.plist, то, по всей вероятности, вы не станете программой, подобной GUI.(Хотя, опять же, можно генерировать GUI без этого).

Вы можете использовать слабые ссылки для тестирования AppKit:

if (NSApplicationMain != NULL) {
  // We're linked with AppKit
}

Это довольно хороший показатель, который вы собираетесь иметьпользовательский интерфейс.Но он не поймет старые приложения Carbon.

Было бы полезно получить дополнительную информацию о том, что вы подразумеваете под словом «я в процессе».Я предполагаю, что вы являетесь фреймворком и хотите вести себя иначе для приложений с графическим интерфейсом, чем для приложений без графического интерфейса пользователясвязан.Это будет работать только для программ, созданных начиная с 10.3, но должно быть достаточно точным (я считаю, что старые приложения QuickDraw все еще связывают Core Graphics в 10.3+, но у меня нет ни одной удобной для проверки).Вероятно, лучший способ - это сделать проверку слабых связей против CGColorCreate(), так как он существует уже давно и вряд ли когда-нибудь исчезнет:

extern CGColorRef CGColorCreate(CGColorSpaceRef space, const CGFloat components[]) 
    __attribute__((weak_import));

...
if (CGColorCreate != NULL) {
  // Linked with CoreGraphics. Probably a GUI

Конечно, все можетсвязь с CoreGraphics и возможность рисовать на экране, но никогда на самом деле рисовать на экране.Они могут связываться с CoreGraphics для обработки изображений.Это может быть более точным, если поискать ApplicationServices.Вы можете протестировать ApplicationServicesVersionNumber против NULL, но это не задокументировано.

Это не поймает приложения X, так как они технически не рисуют на экране.Они отправляют команды в X11.app, который является графическим интерфейсом.Считаете ли вы / usr / X11 / bin / xterm GUI для этой цели?/ usr / X11 / bin / xeyes?

В любом приложении нет какого-либо определенного флага, который бы однозначно говорил «Я рисую на экране».Рисование на экране - это не то, что нужно предварительно объявить.Приложения, которые рисуются на экране, не должны делать это при каждом запуске.Приложения, которые обычно невидимы, могут опционально или время от времени создавать элемент статуса.Трудно придумать одно описание, которое включает GrowlHelperApp.app, Pages.app и /usr/X11/bin/xeyes.

.
...