13

我需要从我的 cooca 应用程序将击键发送到最前面的应用程序。

我已经使用CGEventCreateKeyboardEvent()and为它提供了工作代码AXUIElementPostKeyboardEvent(),但它仅在应用程序未沙盒化时才有效。

我已经在谷歌上搜索了相同的内容,但没有找到任何可行的解决方案。

我看到一个文本应用程序和其他几个人在沙盒环境中做同样的事情,所以我想知道,如果有人帮我弄清楚,aText.app 和其他人如何能够在沙盒环境中发送击键。

谢谢,

4

1 回答 1

4

这实际上是可能的。我在这里提供了一个示例应用程序 - GitHub 上的 SendKey

我走了一条简单的路,从一个简单的 AppleScript 开始:

delay 5

tell application "System Events"
    repeat 10 times
        keystroke "#"
    end repeat
end tell

脚本中的“延迟”只是让我有足够的时间让文本编辑器成为最前面的应用程序。我建议从运行这个脚本开始,看看它做了什么。

然后,我使用默认的应用程序模板创建了一个 Xcode 项目并写道:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    NSString*       scriptPath  = [[NSBundle mainBundle] pathForResource:@"sendkey" ofType:@"scpt"];
    NSURL*          scriptURL   = [NSURL fileURLWithPath:scriptPath];
    NSDictionary*   errors;
    NSAppleScript*  script      = [[NSAppleScript alloc] initWithContentsOfURL:scriptURL error:&errors];

    NSLog( @"%@", errors );

    [script executeAndReturnError:&errors];

    NSLog( @"%@", errors );
}

我在没有打开沙盒的情况下对此进行了测试,以验证它是否有效。然后我打开沙盒,当然,它坏了。但是,幸运的是,有办法解决这个问题。目前,Apple 提供名为com.apple.security.temporary-exception.apple-events的临时权利。而且,您可以请求为“com.apple.systemevents”授予例外。这是我的权利文件的样子:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
   "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>com.apple.security.temporary-exception.apple-events</key>
    <array>
      <string>com.apple.systemevents</string>
    </array>
    <key>com.apple.security.app-sandbox</key>
    <true />
  </dict>
</plist>

一旦我将此权利添加到我的沙盒应用程序并对其进行签名,它就会再次按预期工作。

现在,如果您想发送其他密钥,这个问题和答案将演示如何动态构建您的脚本 - 将变量传递给 applescript

当然,一旦你完成了所有这些工作,你可能会转向 NSAppleEventDescriptor 和相关的类来在代码中构建事件,但我没有使用过这种技术。

请注意,Apple 确实建议您在使用临时授权时执行以下操作:

如果您现在选择不将您的应用程序沙箱化或使用临时异常权利,请使用 Apple 的错误报告系统让 Apple 了解您遇到的问题。Apple 在开发 OS X 平台时会考虑功能请求。此外,请务必使用 iTunes Connect 中的 Review Notes 字段来解释为什么需要例外。

于 2013-04-22T23:44:02.513 回答