Определить, было ли запущено приложение macOS из командной строки (Терминал) - PullRequest
0 голосов
/ 07 октября 2018

У меня есть приложение MacOS с графическим интерфейсом, которое также может запускаться из терминала с необязательными аргументами командной строки.

При запуске с аргументами мне нравится запускать приложение в режиме «cmdline», где я неотображать любой пользовательский интерфейс, но вместо этого общаться только через stdin + stdout.

Я могу определить этот режим cmdline следующим образом:

BOOL cmdMode = NSProcessInfo.processInfo.arguments.count > 1;

(аргумент 0 - это всегда путь к исполняемому файлу, поэтому любые аргументы будутбыть вручную переданы аргументы).

Теперь вот большой вопрос:

Если пользователь вызывает мое приложение без аргументов из терминала (вызывая исполняемый файл приложения в Contents / MacOS , т.е. не через open cmd), мне также нравится переходить в режим cmdline.Как я могу это обнаружить?

Примечание. В более старых версиях OS X передавался аргумент "-psn ...", который, если его нет, можно было использовать для обнаружения запуска из cmdline, но последние версии macOS кажутсябольше не передавать этот аргумент при запуске приложений из Finder, поэтому я больше не могу использовать его для обнаружения.

Обновление

Я понимаю, что могу почти правильнорешить эту проблему, проверив наличие определенных переменных среды:

TERM и PWD устанавливаются только при запуске приложения из терминала, но не из Finder.

Однако мне также нравитсячтобы можно было различить разницу между запуском напрямую (исполняемым в каталоге Contents / MacOS) и запуском с помощью команды open, поскольку я считаю, что open cmd эквивалентен открытию приложения через Finder или из другого приложения через Launch Services.

Короче говоря, вопрос также может быть: Определить, было ли приложение запущено службами запуска


Для записиd, вот значения из environ().Те, которые отмечены звездочкой, присутствуют только при вызове из Terminal.app, но не при запуске из Finder:

    __CF_USER_TEXT_ENCODING=0x1F5:0x0:0x0
*   _=/Applications/Myapp.app/Contents/MacOS/Myapp
    Apple_PubSub_Socket_Render=/private/tmp/com.apple.launchd.laVQnD7IXl/Render
    HOME=/Users/username
*   LANG=en_US.UTF-8
*   LC_ALL=en_US.UTF-8
*   LC_CTYPE=UTF-8
    LOGNAME=username
    PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
*   PWD=/Users/username
    SHELL=/bin/bash
*   SHLVL=1
    SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.KeHv8KNuuk/Listeners
*   TERM_PROGRAM_VERSION=388.1.2
*   TERM_PROGRAM=Apple_Terminal
*   TERM_SESSION_ID=EF2C59E6-D661-45BE-B7EF-7A0E71158C8D
*   TERM=xterm-color
    TMPDIR=/var/folders/hm/ycnxcbwx8xl1v7008k8wnpjh0000gn/T/
    USER=username
    XPC_FLAGS=0x0
    XPC_SERVICE_NAME=0

Однако отсутствуют значения расширений, уникальные для приложений, запускаемых с помощью Launch Services (например,как при двойном щелчке в Finder).

1 Ответ

0 голосов
/ 07 октября 2018

Если вы хотите узнать, какой процесс выполнил вашу программу, вы можете использовать getppid(), чтобы получить идентификатор родительского процесса, а затем проверить этот процесс, чтобы определить, был ли вы выполнен интерактивным процессом оболочки, или Finder, или launchctl,и т.д.

/sbin/launchd - это PID 1 - если родительский PID вашего процесса равен 1, вы были выполнены launchd.

В противном случае вы были выполнены другим процессом - возможно, интерактивной оболочкой иликак подпроцесс другого процесса.Вы можете использовать системный вызов KERN_PROCARGS с sysctl(), чтобы получить имя процесса по его PID.

Вы также можете рассмотреть возможность использования isatty(STDIN): интерактивные оболочки имеютTTY, неинтерактивные оболочки и другие процессы не будут.

...