Включить доступ для вспомогательных устройств программным способом на 10,9
Я хочу включить доступ к вспомогательным устройствам программно на 10.9. На 10,8 и ниже я использовал следующий Applescript для доступа к вспомогательным устройствам:
tell application "System Events" if UI elements enabled is false then set UI elements enabled to true end if end tell
С 10.9 Apple переместила параметры доступности в Системные настройки ➞ Безопасность и конфиденциальность ➞ Конфиденциальность ➞ Доступность. В отличие от предыдущих версий OS X, которая использовала универсальный флажок для всех приложений, новая функциональность в 10.9 позволяет пользователям индивидуально выбирать, какие приложения могут получить контроль над системой, чтобы выполнять свои различные скриптовые функции.
- NSTextField ждет, пока конец цикла не будет обновлен
- Нижний регистр «k» в cocoa
- Как отсортировать NSMutableArray с помощью sortedArrayUsingDescriptors?
- Создание точки останова в Xcode для непризнанного селектора
- Как проспать от сна программно, если крышка закрыта?
Apple НЕ предоставила разработчикам API для программного обеспечения доступности для приложения. Таким образом, Mac OS 10.9 предложит диалоговое окно для разрешения конечного пользователя для обеспечения доступности, когда приложение использует API-интерфейсы доступности. Кроме того, пользователю необходимо перезапустить приложение после включения Accessibility.
Можем ли мы разрешить доступ к вспомогательным устройствам программным способом на 10.9 с использованием Applescript или любых других API? Любая помощь в решении этой проблемы была бы весьма признательна.
- Как сделать ui отзывчивым все время и делать обновление фона?
- используя objc_msgSend для вызова функции Objective C с именованными аргументами
- В чем заключается использование - ?
- Как получить счетчик ссылок NSObject?
- Исключение, вызванное генерируемыми NSOrderedSet
- Ошибка Xcode 4 для обозначения журнала сбоев
- Аргументы в @selector
- Как установить интервал повторения локального уведомления на пользовательский интервал времени?
Это не отвечает на ваш вопрос, но хорошо знать о новом вызове API, который появился в 10.9, и позволяет отображать экран авторизации или обходить его:
NSDictionary *options = @{(id)kAXTrustedCheckOptionPrompt: @YES}; BOOL accessibilityEnabled = AXIsProcessTrustedWithOptions((CFDictionaryRef)options);
Передача YES
заставит экран авторизации появиться, передав NO
он молча пропустит его. Возвращаемое значение совпадает с возвращаемым AXAPIEnabled()
, которое становится устаревшим в 10.9. Чтобы убедиться, что функция доступна в вашей системе, просто сравните ее с NULL
:
if (AXIsProcessTrustedWithOptions != NULL) { // 10.9 and later } else { // 10.8 and older }
Вам нужно добавить ApplicationServices.framework
в свой проект и импортировать в ваш файл .m или .h:
#import
Очень жаль, что экран авторизации не позволяет пользователю авторизировать приложение напрямую, он просто открывает правую часть системных настроек. Что, кстати, вы можете сделать напрямую, не пройдя бесполезный системный диалог:
tell application "System Preferences" set securityPane to pane id "com.apple.preference.security" tell securityPane to reveal anchor "Privacy_Accessibility" activate end tell
или с использованием Objective C:
NSString *urlString = @"x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility"; [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:urlString]];
Это может быть сопряжено с первым fragmentом кода, чтобы проверить, accessibilityEnabled
ли accessibilityEnabled
, передавая @NO
на kAXTrustedCheckOptionPrompt
, предотвращая появление всплывающего windows системы и открывая непосредственно панель параметров доступности:
NSDictionary *options = @{(id)kAXTrustedCheckOptionPrompt: @NO}; BOOL accessibilityEnabled = AXIsProcessTrustedWithOptions((CFDictionaryRef)options); if (!accessibilityEnabled) { NSString *urlString = @"x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility"; [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:urlString]]; }
В то время как ответ @ user2865860 работает хорошо, я бы опубликовал весь образец кода, который отлично работает на 10.9, чтобы сэкономить время на некоторое время. Вам нужно получить права root, поэтому он предложит пользователю ввести пароль.
char *command= "/usr/bin/sqlite3"; char *args[] = {"/Library/Application Support/com.apple.TCC/TCC.db", "INSERT or REPLACE INTO access VALUES('kTCCServiceAccessibility','com.yourapp',0,1,0,NULL);", nil}; AuthorizationRef authRef; OSStatus status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authRef); if (status == errAuthorizationSuccess) { status = AuthorizationExecuteWithPrivileges(authRef, command, kAuthorizationFlagDefaults, args, NULL); AuthorizationFree(authRef, kAuthorizationFlagDestroyRights); if(status != 0){ //handle errors... } }
Вы можете напрямую отредактировать файл TCC.db. Я должен был сделать это, чтобы установить Divvy без взаимодействия с пользователем. Просто замените com.mizage.divvy на свою программу.
sudo sqlite3 /Library/Application\ Support/com.apple.TCC/TCC.db "INSERT INTO access VALUES('kTCCServiceAccessibility','com.mizage.divvy',0,1,1,NULL);"
Чтобы удалить запись:
sudo sqlite3 /Library/Application\ Support/com.apple.TCC/TCC.db "delete from access where client='com.mizage.divvy';"
Я нашел следующий fragment кода, который правильно запрашивает разрешения на доступность в OS X 10.9:
if (AXIsProcessTrustedWithOptions != NULL) { // 10.9 and later const void * keys[] = { kAXTrustedCheckOptionPrompt }; const void * values[] = { kCFBooleanTrue }; CFDictionaryRef options = CFDictionaryCreate( kCFAllocatorDefault, keys, values, sizeof(keys) / sizeof(*keys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); return AXIsProcessTrustedWithOptions(options); } // OS X 10.8 and older
Я боролся с этим сам, и после небольшого исследования я обнаружил следующее:
-
Взлом базы данных sqlite имеет большой недостаток в использовании служб авторизации. Сначала появится диалоговое окно с сообщением пользователю о том, что приложение хочет установить помощник утилиты (хотя это всего лишь одна
SMJobSubmit
запуска с использованиемSMJobSubmit
). Во-вторых, он не работает для изолированных приложений и, следовательно, нет магазина приложений. -
@Max Al Faeakh использует
AuthorizationExecuteWithPrivileges
который устарел. Вам нужно использовать launchd с указанным вышеSMJobSubmit
. Во всяком случае, это все еще требует авторизации. Для этого также требуется дополнительное приложение, подобное этому.
Я думаю, лучше всего использовать:
NSDictionary *options = @{(id)kAXTrustedCheckOptionPrompt: @YES}; BOOL accessibilityEnabled = AXIsProcessTrustedWithOptions((CFDictionaryRef)options);
или
NSDictionary *options = @{(id)kAXTrustedCheckOptionPrompt: @NO}; BOOL accessibilityEnabled = AXIsProcessTrustedWithOptions((CFDictionaryRef)options);
и открыть панель предпочтений вручную, используя, например, структуру сценариев моста:
SBSystemPreferencesApplication *prefs = [SBApplication applicationWithBundleIdentifier:@"com.apple.systempreferences"]; [prefs activate]; SBSystemPreferencesPane *pane = [[prefs panes] find:^BOOL(SBSystemPreferencesPane *elem) { return [[elem id] isEqualToString:@"com.apple.preference.security"]; }]; SBSystemPreferencesAnchor *anchor = [[pane anchors] find:^BOOL(SBSystemPreferencesAnchor *elem) { return [[elem name] isEqualToString:@"Privacy_Accessibility"]; }]; [anchor reveal];
Класс SBSystemPreferencesPane
SBSystemPreferences.h
файла SBSystemPreferences.h
который может быть сгенерирован:
sdef "/Applications/System Preferences.app" | sdp -fh --basename SBSystemPreferences -o SBSystemPreferences.h
Спасибо за образцы сценария оболочки из @NightFlight, которые действительно полезны. Я использовал это с AppleScript в приложении Python, например:
set sh to "touch /private/var/db/.AccessibilityAPIEnabled && sqlite3 \\"/Library/Application Support/com.apple.TCC/TCC.db\\" \\"INSERT or REPLACE INTO access VALUES('kTCCServiceAccessibility','com.godevnode',0,1,0,NULL);\\"" do shell script sh with administrator privileges
Он работал хорошо для меня в коде Python как строка.
Редактировать (7 ноября 2014 года):
Если вы хотите попробовать это в редакторе AppleScript, используйте несколько другой escape-код, как показано ниже:
set sh to "touch /private/var/db/.AccessibilityAPIEnabled && sqlite3 \"/Library/Application Support/com.apple.TCC/TCC.db\" \"INSERT or REPLACE INTO access VALUES('kTCCServiceAccessibility','com.godevnode',0,1,0,NULL);\"" do shell script sh with administrator privileges
Для Mac OS X до 10.9 это еще проще:
accessibility_api_file = "/private/var/db/.AccessibilityAPIEnabled" def __enable_accessibility_api(): try: script = 'do shell script "touch %s" with administrator ' \ 'privileges' % accessibility_api_file result = applescript.AppleScript(script).run() log.debug("Tried to enable accessibility api, result=" + result) return True except applescript.ScriptError as err: log.error(str(err)) return False
Просто нужно коснуться одного файла. AppleScript, упомянутый выше в коде Python, также может использоваться на других языках.
Всем спасибо.
Я выхожу из windows входа в систему, чтобы обеспечить контроль только тем элементам, которые мы хотим получить в каждом сеансе:
# Enable Service Accessibility for Textpander and others # Clear the acess table. sqlite3 /Library/Application\ Support/com.apple.TCC/TCC.db "DELETE FROM access" # Enter the access we wish to have. sqlite3 /Library/Application\ Support/com.apple.TCC/TCC.db "INSERT INTO access VALUES ('kTCCServiceAccessibility','com.apple.systempreferences',0,1,1,NULL)" sqlite3 /Library/Application\ Support/com.apple.TCC/TCC.db "INSERT INTO access VALUES ('kTCCServiceAccessibility','de.petermaurer.textpanderdaemon',0,1,1,NULL)"
Sqlite3 «взломать» отлично.
Мне пришлось использовать разрешения «1,1,1» (что бы это ни значило), чтобы сделать эту работу.
Обратите внимание, что комбинация разрешений, а не клиент (то есть имя программы) является уникальным ключом базы данных.