LaunchAgents для приложения с графическим интерфейсом
Я хотел бы запускать свое приложение каждый раз, когда пользователь входит в систему.
Я добавил plist-файл в папку /Libray/LaunchAgents:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>KeepAlive</key>
<false/>
<key> LaunchOnlyOnce</key>
<true/>
<key>OnDemand</key>
<false/>
<key>RunAtLoad</key>
<true/>
<key>Label</key>
<string>com.mycompany.myapp</string>
<key>ProgramArguments</key>
<array>
<string>/Applications/mayapp.app/Contents/MacOS/myapp</string>
</array>
</dict>
</plist>
Все выглядит хорошо, приложение загружается, однако, когда я закрываю свое приложение, оно запускается сервисом launchd.
Какой ключ я должен добавить / изменить в моем файле plist, чтобы предотвратить постоянный перезапуск моего приложения.
3 ответа
Если вы хотите запустить обычное приложение при входе в систему, я бы порекомендовал использовать API списка общих файлов LaunchServices, а не launchd. Вместо того, чтобы устанавливать plist launchd, вы можете просто использовать этот API, чтобы добавить свое приложение к элементам входа пользователя (те, которые вы видите на преф-панели "Учетные записи" в Системных настройках). Преимущества этого: а) для пользователя более очевидно, почему приложение запускается при входе в систему, б) пользователю легче удалить его, и в) если пользователь удаляет ваше приложение, launchd будет жаловаться на ошибки консоли. когда не удается запустить (теперь отсутствует) приложение.
Похоже, что нет никакой справочной документации по API, но соответствующие функции находятся в LSSharedFileList.h. Код для этого будет выглядеть примерно так:
#import <CoreServices/CoreServices.h>
...
LSSharedFileListRef loginItemList = LSSharedFileListCreate(kCFAllocatorDefault, kLSSharedFileListSessionLoginItems, NULL);
if (loginItemList != NULL)
{
LSSharedFileListRef myItem = LSSharedFileListInsertItemURL(loginItemList, kLSSharedFileListItemLast, NULL, NULL, (CFURLRef)[[NSBundle mainBundle] bundleURL], NULL, NULL);
//We don't do anything with the new item, but we need to release it so it doesn't leak
if (myItem != NULL)
CFRelease(myItem);
CFRelease(loginItemList);
}
Если вы хотите, чтобы этот элемент запускался для всех пользователей, а не только для текущего зарегистрированного пользователя, вы можете использовать kLSSharedFileListGlobalLoginItems вместо kLSSharedFileListSessionLoginItems.
Удалите ключ Keep Alive и запустите ключ только один раз... так как вам нужно запустить приложение только один раз. Вот пример кода для запуска приложения с именем приложения входа в систему.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>RunAtLoad</key>
<true/>
<key>Label</key>
<string>com.apple.LoginApp</string>
<key>Program</key>
<string>/Library/Log Files/LoginApp.app/Contents/MacOS/LoginApp</string>
<key>onDemand</key>
<false/>
</dict>
</plist>
Надеюсь это поможет
Я вижу две проблемы: основная из них заключается в том, что у вас есть <key>OnDemand</key><false/>
, который говорит launchd, что агент должен быть в живых (и это, кажется, переопределяет <key>KeepAlive</key><false/>
, что означает с точностью до наоборот). Вторая проблема заключается в том, что перед именем ключа есть пробел <key> LaunchOnlyOnce</key><true/>
, Простое решение: удалите оба ключа OnDemand и LaunchOnlyOnce, и все должно работать нормально.