«потому что он не защищен SIP» - ошибка события Apple в macOS Mojave - PullRequest
0 голосов
/ 25 сентября 2018

У меня есть корректно изолированное приложение в macOS, Objective-C, которое взаимодействует со сторонними приложениями Apple Events (например, Adobe InDesign).

В MacOS Mojave все ломается, вызывая новый SIP от Apple (https://developer.apple.com/library/archive/documentation/Security/Conceptual/System_Integrity_Protection_Guide/Introduction/Introduction.html) не разрешает связь.

Я пока не нашел решения. Любая помощь приветствуется.

Это сообщение об ошибке:

пропущенодобавление сценариев "/ Library / ScriptingAdditions / Adobe Unit Types.osax", поскольку оно не защищено SIP.

Это довольно хорошее резюме проблемы: https://www.felix -schwarz.орг / блог / 2018/06 / яблочно-событийно-песочница-в-MacOS-Мохаве

Ответы [ 2 ]

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

Давайте проясним различие между SIP (защита целостности системы) и TCC (прозрачность, согласие, контроль: в основном все диалоговые окна «это приложение хочет получить доступ к этой услуге», управляемые в разделе Безопасность и конфиденциальность).Mojave включает изменения в обоих, и их влияние на события Apple и AppleScript описано в примечаниях к выпуску Mojave .

Во-первых, SIP: сообщение журнала о типах модулей Adobe, которые не загружаются,действительно, из-за изменений в SIP - Hardened Runtime означает, что глобально установленные сторонние добавления сценариев больше не разрешены - но если вы не используете принудительные действия Adobe, это не повлияет на ваше приложение.

Далее, TCC: если отправка событий Apple из вашего приложения не удалась, когда оно работало в 10.13, то ваша проблема, скорее всего, связана с TCC.Ошибка для отслеживания: errAEEventNotPermitted, -1743: это означает, что TCC заблокировал событие.(-600 и -10004 указывают на проблемы с правами на доступ к песочнице.) Если вы сначала не видите диалоговое окно TCC, вам, скорее всего, не хватает записи NSAppleEventsUsageDescription в вашем Info.plist: это требуется при сборке с использованием SDK 10.14.

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

0 голосов
/ 26 сентября 2018

Apple все еще нужно над этим работать, она не идеальна, она не удобна для пользователя, она плохо документирована.Но вот рабочее решение.

Начиная с OSX 10.14 (Mojave), вы должны спросить OSX System Integrity Protection (SIP), разрешил ли пользователь вашему приложению общаться с другими.

Для созданиячтобы это работало, вам нужно добавить запись в файл .plist вашего приложения:

key: NSAppleEventsUsageDescription
value: [Some description why you need to use AppleEvents]

enter image description here

Примечание: Вы можетене использовать больше записей для большего количества приложений.Это одна запись.Так что выбирайте свое описание с умом.Это описание будет отображаться в диалоговом окне Apple с просьбой принять пользователя.

Если у вас есть служба XPC, как у меня, поместите ее в свое ОСНОВНОЕ приложение, а не в службу.

Сейчас вВаше приложение - перед использованием событий Apple - проверьте текущее состояние (разрешены AppleEvents или нет).Я написал этот метод:

- (BOOL)checkSIPforAppIdentifier:(NSString*)identifier {

    // First available from 10.14 Mojave
    if (@available(macOS 10.14, *)) {

        OSStatus status;
        NSAppleEventDescriptor *targetAppEventDescriptor;

        targetAppEventDescriptor = [NSAppleEventDescriptor descriptorWithBundleIdentifier:identifier];

        status = AEDeterminePermissionToAutomateTarget(targetAppEventDescriptor.aeDesc, typeWildCard, typeWildCard, true);

        switch (status) {
            case -600: //procNotFound
                NSLog(@"Not running app with id '%@'",identifier);
                break;

            case 0: // noErr
                NSLog(@"SIP check successfull for app with id '%@'",identifier);
                break;

            case -1744: // errAEEventWouldRequireUserConsent
                // This only appears if you send false for askUserIfNeeded
                NSLog(@"User consent required for app with id '%@'",identifier);
                break;

            case -1743: //errAEEventNotPermitted
                NSLog(@"User didn't allow usage for app with id '%@'",identifier);

                // Here you should present a dialog with a tutorial on how to activate it manually
                // This can be something like
                // Go to system preferences > security > privacy
                // Choose automation and active [APPNAME] for [APPNAME]

                return NO;

            default:
                break;
        }
    }
    return YES;
}

Назовите его так:

[self checkSIPforAppIdentifier:@"com.apple.mail"];

Подробную информацию вы можете найти в AppleEvents.h - вот копия для используемого метода:

AEDeterminePermissionToAutomateTarget ()

Обсуждение: Определяет, может ли текущее приложение отправлять AppleEvent с указанным eventClass и eventID в приложение, описанное как targetAddressDesc.

Mac OS 10.14 ипозже налагаются дополнительные требования на приложения, когда они отправляют AppleEvents другим приложениям, чтобы гарантировать, что пользователи знают и соглашаются разрешить такой контроль или обмен информацией.Как правило, это связано с тем, что пользователю в первый раз предлагается безопасный способ отправки приложения AppleEvent другому приложению.

Если пользователь соглашается, то это приложение может отправлять события целевому объекту.Если пользователь не дает согласия, то любые будущие попытки отправить AppleEvents приведут к ошибке с возвратом errAEEventNotPermitted.Определенные AppleEvents разрешено отправлять без запроса пользователя.Передайте typeWildCard для eventClass и eventID, чтобы определить, разрешено ли отправлять каждое событие из этого приложения в целевое устройство.

Приложения могут определить, не отправляя AppleEvent целевому приложению, разрешено ли им отправлять AppleEventsк цели с помощью этой функции.Если askUserIfNeeded имеет значение true, и у этого приложения еще нет разрешения на отправку AppleEvents в целевую систему, то пользователю будет предложено предоставить разрешение;если значение askUserIfNeeded - false и разрешение не было предоставлено, будет возвращено значение errAEEventWouldRequireUserConsent.

Целевой объект AEAddressDesc должен ссылаться на уже работающее приложение.

Results

Если текущийприложению разрешено отправлять AppleEvent указанному объекту, тогда noErr будет возвращено.Если текущему приложению не разрешено отправлять событие, будет возвращено errAEEventNotPermitted.Если целевое приложение не запущено, будет возвращен procNotFound.Если askUserIfNeeded имеет значение false, и это приложение еще не разрешено отправлять AppleEvents к цели, тогда будет возвращено errAEEventWouldRequireUserConsent.

Потоки в Mac OS X:

Потоковая защита начиная с версии 10.14.Не вызывайте эту функцию в главном потоке, потому что может потребоваться произвольное время для возврата, если пользователю необходимо запросить согласие.

Параметры:

target:

Aуказатель на дескриптор адреса.Перед вызовом AEDeterminePermissionToAutomateTarget вы устанавливаете дескриптор для определения целевого приложения для события Apple.Дескриптор целевого адреса должен ссылаться на работающее приложение.Если целевое приложение находится на другом компьютере, то для этого пользователя на этом компьютере должно быть включено Remote AppleEvents.

theAEEventClass: класс события Apple, для которого необходимо определить разрешение.

theAEEventID: идентификатор события Apple, для которого необходимо определить разрешение.

askUserIfNeeded: логическое значение;если true, и если у этого приложения еще нет разрешения на отправку событий целевому приложению, то предложите пользователю получить разрешение.Если ложь, не предлагайте пользователю.

Вывод:

Как упоминалось ранее, это не идеально.

  • целевое приложение должно запускаться - в противном случае оно вернет -600
  • После отказа пользователь может активировать его только вручную - это не очень хорошо и гладко.
  • Его потокобезопасен, поэтому вам следуетне вызывать его в главном потоке (кроме диалога для ручной активации)
...