Удаление элементов, установленных с помощью.app, когда пользователь удаляет его, включая помощников SMJobBless

Краткая версия: возможно ли удалить вспомогательные инструменты, которые были установлены приложением (SMJobBless() и т.д.) когда приложение будет удалено? Если так, то как?

Длинная версия:

К сожалению, для приложения Mac, которое мы разрабатываем, требуются привилегии администратора для выполнения случайных операций, а также для фоновой задачи, позволяющей подключаться к плагинам других приложений, даже если само приложение не запущено (это может быть непривилегированным)., Приложение будет подписано сертификатом ID разработчика и распространяется только за пределами App Store.

Мы бы хотели, чтобы приложение было "добропорядочным гражданином", насколько это возможно, даже при удалении.

Для фоновой задачи мы используем элемент входа, созданный с помощью SMLoginItemSetEnabled(), Это не удивительно, потому что обмен сообщениями XPC не работает (мы используем CFMessagePort вместо этого - приветствуются альтернативные предложения), но если пользователь удаляет приложение, элемент входа в систему по крайней мере больше не загружается при следующем входе в систему. Я подозреваю, что где-то в системе все еще есть его след, но используется исполняемый файл внутри пакета.app, и когда он исчезает, элемент входа больше не запускается.

Для случайных операций, требующих прав администратора, у нас есть привилегированный вспомогательный инструмент, который наше приложение устанавливает с помощью SMJobBless() и которая реализует именованную службу XPC, поэтому задача раскручивается по требованию, когда получает сообщение от основного приложения. Это то, что Apple рекомендует и описывает в своем образце Even Better Authorization.

Исполняемый файл помощника копируется в /Library/PrivilegedHelperTools/ от SMJobBless() и встроенный файл launchd.plist заканчивается в /Library/LaunchDaemons/, Несмотря на то, что в ОС есть информация о том, какое приложение "владеет" помощником, похоже, что оно не удаляется, когда пользователь удаляет приложение. Образец Apple молчит об удалении, кроме uninstall.sh скрипт, который, очевидно, предназначен для использования только во время разработки. Нам не нужен этот помощник, пока приложение не запущено, поэтому его установка в качестве полноценного демона запуска немного излишня, но мы также хотели бы избежать повторного раздражения пользователя с помощью запроса пароля. Кроме того, Apple советует не запускать другой код с правами администратора, кроме SMJobBless() в эти дни - например SMJobSubmit() помечен как устаревший.

Итак, как мы убираем за собой?

я обнаружил SMJobRemove(), но (а) когда мы будем называть это в нашем случае - вы не можете запустить код при удалении пакета.app, или можете? и (б) это на самом деле не кажется, чтобы очистить.

Единственные две вещи, которые я могу придумать, не очень-то удовлетворяют:

  1. Какое-то приложение или скрипт для удаления. Но это тоже кажется довольно уродливым.
  2. Не беспокойтесь об этом и просто оставьте беспорядок, когда пользователь удалит наше приложение.

4 ответа

Решение

Похожий вопрос был на форумах разработчиков Apple по адресу https://forums.developer.apple.com/thread/66821 - рекомендация Apple - это механизм ручного удаления, который потребляет как можно меньше ресурсов, если пользователь этого не делает. сделай это.

Кроме того, сотрудники Apple DTS рекомендовали внедрить механизм самоинсталляции в привилегированном демоне запуска, который будет запускаться из приложения через XPC. Это то, с чем мы идем.

Одним из решений, которое вы могли бы рассмотреть, является включение сценария или программы удаления в ваш пакет.app.

Затем вы можете передать путь этого небольшого инструмента вашему вспомогательному инструменту (через IPC) и запустить деинсталлятор, тем самым удалив себя. Вы должны быть осторожны, чтобы компоненты были удалены в правильном порядке, но это может быть сделано для работы.

Я думаю, что единственное решение, которое у вас есть сейчас, - это использовать код деинсталляции оболочки, который вы упомянули, чтобы физически удалить привилегированного помощника с диска или создать для него деинсталлятор. В любом случае вам нужно будет попросить пользователя ввести свой пароль. Это то, что делают все установщики / деинсталляторы, которым требуется привилегированный доступ к системе, и по очень веской причине. Вот почему я, как чума, избегаю использовать привилегированных помощников, но я понимаю, что иногда вам действительно нужно. Я не думаю, что это хорошо, что вы оставляете такого помощника в системе пользователя, потому что он перезагрузится при следующем запуске компьютера пользователем.

Я только что проверил заголовок ServiceManagement.h, и они утверждают, что SMJobRemove будет заменен API, который будет доступен через libxpc в будущем. (Иногда вам действительно нужно перейти к заголовкам, чтобы получить дополнительную информацию, которую вам не предоставит документация.) Надеюсь, эта обещанная замена удалит ее для нас. Тем не менее, я бы подал отчет об ошибке и попросил об этом улучшении.

Вы правы, что Apple не предоставляет API для удаления вспомогательного инструмента, установленного с SMJobBlessони не делают этого автоматически. Что касается того, почему macOS не выполняет удаление автоматически, я предполагаю, что в macOS принципиально нет единой концепции «установки». Хотя принято, чтобы приложения располагались в папке / Applications (и в некоторых других местах), вполне допустимо, чтобы приложения находились и запускались из любой точки системы, включая внешние диски и сетевые диски. Например, следует ли macOS удалять вспомогательные инструменты, когда приложения исчезают из-за отключения диска, на котором они находятся?

С точки зрения того, как удалить, для этого требуется разрешение root, и поэтому, если реально использовать вспомогательный инструмент, удаление - самый простой вариант. Вы можете попросить ваше приложение через XPC сказать помощнику, что нужно удалить себя. Вот того, как это сделать примерв Swift ; это часть SwiftAuthorizationSample . Основная идея:

  • Используйте инструмент командной строки, чтобы выгрузить вспомогательный инструмент
  • Удалить исполняемый файл вспомогательного инструмента
  • Удалите вспомогательный инструмент launchd plist

Но здесь есть немного дополнительных сложностей, потому что launchctl не позволит разгрузить запущенный процесс.

Другие вопросы по тегам