【问题标题】:Relaunch OS X app to execute CGEventTapCreate() when AXIsProcessTrusted() is true当 AXIsProcessTrusted() 为真时,重新启动 OS X 应用程序以执行 CGEventTapCreate()
【发布时间】:2016-06-06 23:12:28
【问题描述】:

我的应用程序的一个功能是检测keyDown 事件并对某些特定键进行处理。

所以,我使用CGEventTapCreate 来解决我的问题,我的代码是这样的:

   if let tap = CGEventTapCreate(.CGHIDEventTap, .HeadInsertEventTap, .Default, CGEventMask(1 << CGEventType.KeyDown.rawValue), callBack, nil) {
       let runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, tap, 0)
       CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode)
       CGEventTapEnable(tap, true)
       CFRunLoopRun()
   }

另外,我处理的流程信任如下:

let options = [kAXTrustedCheckOptionPrompt.takeUnretainedValue() as NSString: false]
let processTrusted = AXIsProcessTrustedWithOptions(options)
if processTrusted {
    // do CGEventTapCreate()
} else {
    // check again 1s later
    performSelector("checkMethod", withObject: nil, afterDelay: 1)
}

它将每秒调用一次,直到 processTrusted 为真。

然后奇怪的事情发生了:

当我在 Xcode 中运行应用程序并在 Privacy_Accessibility 中添加信任 Xcode 时,一切正常。但是当我将应用程序存档并将Export as a Mac Application 运行到我的桌面时,CGEventTapCreate() 就不起作用了。

之后我发现了这个帖子Enable access for assistive devices programmatically on 10.9,它注意到我需要在AXIsTrustedProcess()之后重新启动应用程序。

您知道,告诉用户自己重新启动应用程序并不是一个好主意。所以我尝试以编程方式重新启动它并将这些代码添加到if processTrusted {}

NSWorkspace.sharedWorkspace().launchApplication(NSProcessInfo.processInfo().processName)
NSApplication.sharedApplication().terminate(nil)

也就是说,当我在Privacy_Accessibility 中勾选应用程序时,它会自动重新启动。

又来了一件奇怪的事:

应用程序真正终止并自动启动。但是当它完成重新启动时,应用程序的 Privacy_Accessibility 没有勾选。

真的让我很困惑,希望有人告诉我处理进程信任的正确方法并正确执行CGEventTapCreate()

谢谢!

【问题讨论】:

  • 我很确定您启动的应用程序继承了您当前的权限,但没有官方答案的参考。也就是说,由于您的应用缺少“信任”可访问性,当它调用launchApplication 时,该进程也不是“受信任”的。
  • @Smilin Brian 这是有道理的。据此,我可以以编程方式刷新辅助功能吗?或者是否有一种方法可以启动具有最新可访问性的应用程序?
  • 我认为诀窍是让系统启动应用程序,以便 it 成为“父”进程。也许是这样的:[NSTask launchedTaskWithLaunchPath:@"/bin/sh" arguments:[NSArray arrayWithObjects:@"-c", [NSString stringWithFormat:@"sleep 3 ; /usr/bin/open '%@'", [[NSBundle mainBundle] bundlePath]], nil]];
  • @SmilinBrian 谢谢,你是对的!我使用您的代码,然后致电NSApplication.sharedApplication().terminate(nil),然后应用程序会以正确的辅助功能重新启动。所以,请回答这个问题,我会设置为正确答案。
  • 您是否成功检测到用户何时在系统偏好设置中允许该应用?我正在尝试实现类似的事情,但在重新启动应用程序之前,AXIsProcessTrustedWithOptions 总是返回 false,即使它不应该返回。

标签: objective-c swift macos cocoa cgeventtap


【解决方案1】:

轮询AXIsProcessTrusted 并自动重新启动是一个不错的选择。用户经常对这个过程感到困惑,所以任何有助于他们更轻松的事情都是好的。

我很确定您启动的应用程序继承了您当前的权限,但没有方便的引用来备份它。我发现在使用CGEventTaps 调试应用程序时,我还必须为 Xcode 提供我的应用程序请求/需要的辅助功​​能权限。

但您可以通过让系统为您启动应用来解决此问题。试试:

[NSTask launchedTaskWithLaunchPath:@"/bin/sh" arguments:[NSArray arrayWithObjects:@"-c", [NSString stringWithFormat:@"sleep 3 ; /usr/bin/open '%@'", [[NSBundle mainBundle] bundlePath]], nil]];

【讨论】:

    猜你喜欢
    • 2017-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-11
    • 1970-01-01
    • 2014-06-30
    • 2010-11-21
    相关资源
    最近更新 更多