我想在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版本中,苹果已经将辅助功能选项移动到系统偏好设置➞安全和隐私➞隐私➞辅助功能。与OS以前的版本不同,OS对所有应用程序都使用通用的复选框,10.9中的新功能允许用户单独选择哪些应用程序可以控制系统,以执行各种脚本功能。
Apple没有向开发人员提供任何API来以编程方式启用应用程序的可访问性。因此,当应用程序使用可访问性API时,MacOS10.9将提示终端用户权限以启用可访问性。此外,用户必须在启用辅助功能后重新启动应用程序。
我们可以使用Applescript或任何其他API在10.9上以编程方式启用对辅助设备的访问吗?任何帮助解决这个问题的人都将不胜感激。
发布于 2013-08-08 16:26:55
这并没有回答您的问题,但很高兴了解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
传递给kAXTrustedCheckOptionPrompt
来测试是否accessibilityEnabled
,同时阻止出现系统弹出窗口,而不是直接打开可访问性首选项窗格:
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]];
}
发布于 2019-05-19 17:33:43
我建议不要使用所有的sqlite3和AppleScript hack,因为它们将来可能会停止工作,也有一个合适的api来解决这个问题。
除此之外,你可以实际监控用户是否点击了你的应用的辅助功能设置,这样你就可以在用户授予权限时执行一些操作。
(Swift 5,在莫哈韦,卡特琳娜,大苏尔)上测试
读取权限
private func readPrivileges(prompt: Bool) -> Bool {
let options: NSDictionary = [kAXTrustedCheckOptionPrompt.takeRetainedValue() as NSString: prompt]
let status = AXIsProcessTrustedWithOptions(options)
return status
}
accessibility中的更改监控:
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()
以获取新状态。
您需要延迟,因为需要一段时间才能反映出更改。
在监控时你需要记住的另一件事是,任何获得不同权限的应用程序都会触发通知,所以如果用户授予或撤销了一个不同的应用程序,你仍然会收到通知。
此外,当您不再需要观察者时,不要忘记删除它。
编辑:
发布于 2013-12-14 18:18:57
虽然@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...
}
}
https://stackoverflow.com/questions/17693408
复制相似问题