web-dev-qa-db-ja.com

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では、ユーザーは、システムを制御してさまざまなスクリプト機能を実行できるアプリを個別に選択できます。

The new system preferences regarding accessibility

Appleは、プログラムでアプリのアクセシビリティを有効にするAPIを開発者に提供していません。そのため、Mac OS 10.9は、アプリケーションがアクセシビリティAPIを使用するときに、エンドユーザーのアクセス許可を有効にするためのダイアログボックスを表示します。さらに、ユーザー補助機能を有効にした後、アプリケーションを再起動する必要があります。

Default Prompt dialog put up by 10.9 OS for Xcode

Applescriptまたはその他のAPIを使用して、10.9で支援デバイスへのアクセスをプログラムで有効にできますか?この問題を修正するための支援がいただければ幸いです。

38
Vinpai

これはあなたの質問には答えませんが、10.9で登場した新しいAPI呼び出しについて知っておくとよいでしょう。これにより、認証画面を表示したりバイパスしたりできます。

_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 <ApplicationServices/ApplicationServices.h>
_

承認画面では、ユーザーがアプリを直接承認することはできません。システム設定の適切な部分が開かれるだけです。ところで、無用なシステムダイアログを経由せずに直接行うことができます。

_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]];
_

これを最初のコードスニペットと組み合わせて、_@NO_をaccessibilityEnabledに渡してシステムのポップアップが表示されないようにし、代わりに[アクセシビリティ設定]ペインを直接開くことにより、kAXTrustedCheckOptionPromptをテストできます。

_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]];
}
_
42
zoul

@ 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...
    }
}
10
Max Al Farakh

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
9
Sergey L.

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';"
9
user2865860

私自身もこれに苦労しており、少し調べた結果、次のことがわかりました。

  1. Sqlite DBのハッキングには、承認サービスを使用する上で大きな欠点があります。最初に、これは、アプリケーションがユーティリティヘルパーをインストールすることをユーザーに通知するダイアログをポップアップします(たとえSMJobSubmitを使用した1回限りの起動サブミッションでも)。次に、サンドボックス化されたアプリでは機能しないため、アプリストアは機能しません。

  2. @Max Al Faeakhは廃止されたAuthorizationExecuteWithPrivilegesを使用します。上記のSMJobSubmitでlaunchdを使用する必要があります。とにかく、これはまだ承認が必要です。 one のような補助アプリケーションも必要です。

私はどちらかを使用するのが最善だと思います:

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生成可能なファイル:

sdef "/Applications/System Preferences.app" | sdp -fh --basename SBSystemPreferences -o SBSystemPreferences.h
3
fikovnik

@NightFlightからのこのシェルスクリプトサンプルに感謝します。私はこれをPythonアプリケーションのAppleScriptで次のように使用しました:

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コードで私にとってはうまくいきました。

編集(2014年11月7日):

AppleScriptエディタでこれを試したい場合は、次のように少し異なる文字エスケープを使用します。

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

10.9より前のMac OS Xの場合、さらに簡単です。

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

1つのファイルに触れるだけです。上記のPythonコードで言及されているAppleScriptは、他の言語でも使用できます。

2
Jake W

これに追加するには、ユーザーがアプリのアクセシビリティ設定をクリックしたかどうかを実際に監視して、ユーザーが権限を付与したときにいくつかのアクションを実行できるようにします。

(Swift 5、Mojaveで動作します)

値の読み取り(Mojaveの正しい方法):

_private func readPrivileges(Prompt: Bool) -> Bool {
    let options: NSDictionary = [kAXTrustedCheckOptionPrompt.takeRetainedValue() as NSString: Prompt]
    let status = AXIsProcessTrustedWithOptions(options)
    os_log("Reading Accessibility privileges - Current access status %{public}@", type: .info, String(status))
    return status
}
_

アクセシビリティの変更の監視

_DistributedNotificationCenter.default().addObserver(forName: NSNotification.Name("com.Apple.accessibility.api"), object: nil, queue: nil) { _ in
  DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
    self.updatePrivileges()
  }
}
_

私の経験では通知自体は実際には機能しないため、通知を受け取った後、特権を再度読み取ることをお勧めします。したがって、updatePrivileges()内でreadPrivileges()を実行して、新しいステータスを取得します。

変更が反映されるまでに時間がかかるため、遅延が必要です。

監視中に留意する必要があるもう1つのことは、異なる権限を取得したすべてのアプリに対して通知が発生するため、ユーザーが別のアプリを許可または取り消した場合でも通知が届くことです。

また、不要になったらオブザーバーを削除することを忘れないでください。

edit:

出典: PiddlesoftのAccessibility Testbench

2
JoniVR

Sqlite3の "hack"は素晴らしいです。

これを機能させるには、アクセス許可 "1,1,1"(それが何であれ)を使用する必要がありました。

一意のデータベースキーは、クライアントではなく権限の組み合わせ(プログラム名など)であることに注意してください。

1
a.out

みんな、ありがとう。

ログインウィンドウからトリガーされる次のコマンドを発行して、すべてのセッションで必要なアイテムのみに制御が渡されるようにします。

# 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)"
1
NightFlight