重新启动OS X应用程序以在AXIsProcessTrusted()为true时执行CGEventTapCreate()

时间:2016-02-24 15:19:19

标签: objective-c swift macos cocoa cgeventtap

我的应用程序的一项功能是检测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为true之前,它将每秒调用一次。

然后发生了奇怪的事情:

  

当我在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()

谢谢!

1 个答案:

答案 0 :(得分:3)

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

我非常确定您启动的应用程序会继承您当前的权限,但不能提供便于备份的应用程序。我发现在使用CGEventTap调试应用程序时,我还必须为Xcode提供我的应用程序请求/要求的辅助功能权限。

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

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