【问题标题】:Error 1002 in applescript that uses "key code" when called from macOS app从 macOS 应用程序调用时使用“密钥代码”的 applescript 中出现错误 1002
【发布时间】:2019-08-24 16:46:15
【问题描述】:

我正在尝试从我的 macOS 应用程序(Mojave、Xcode 10.3)运行 AppleScript。但是,当从应用程序运行 AppleScript 时,我收到此错误:

/Users/my_username/Desktop/test_apple_script.scpt: execution error: System Events got an error: osascript is not allowed to send keystrokes. (1002)

根据其他帖子,我确保我的应用程序可以控制我的计算机(系统偏好设置 > 安全和隐私 > 隐私 > 可访问性),并且它还可以控制系统事件(系统偏好设置 > 安全和隐私 > 隐私 >自动化)。

这是我的 AppleScript:

tell application "System Events"
    key code 48 using {command down}
end tell

脚本在脚本编辑器中运行时有效(我只需要在系统偏好设置 > 安全和隐私 > 隐私 > 可访问性中授予脚本编辑器访问权限)。

这是我用来从我的应用程序运行 Apple 脚本的代码(通过 osascript):

let proc = Process()
proc.launchPath = "/usr/bin/env"
proc.arguments = ["/usr/bin/osascript","/Users/my_username/Desktop/test_apple_script.scpt"]
proc.launch()

当我运行一个只显示通知的简单 AppleScript 时,这段代码可以完美运行:

tell application "System Events"
    display dialog "Test"
end tell

我怎样才能让我的 AppleScript 从我的 macOS 应用程序中运行,就像我在脚本编辑器中运行它时一样?

编辑: 对于更多上下文,这里的命令选项卡大小写只是一个示例。我试图通过单击我的应用程序中的按钮来找到一种可通用的方法来模拟键盘快捷键(例如,用户单击“剪切”按钮并且应用程序的行为就像用户刚刚按下了 command + x)。可能有比使用 AppleScript 更好的方法,但我知道使用 AppleScripts 可以做我想做的事情。

编辑:如果我最初的问题不清楚,显示通知的简单 AppleScript 已经在我的应用程序中运行。当我尝试运行模拟用户从键盘输入的 AppleScript 时,就会出现问题。

编辑:这里的代码暂时对我有用,但它不再有效。我根本没有更改代码。我只是再次运行我的应用程序。

let PlayPauseScript = "tell application \"Spotify\"\n playpause\n end tell"\"test\"\n end tell"
if let scriptObject = NSAppleScript(source: PlayPauseScript) {
    scriptObject.executeAndReturnError(nil)
}

编辑: 这是当前问题所在。根据建议,我将其添加到我的 info.plist,现在 Spotify AppleScript 始终有效(通过 NSAppleScript 调用时):

<key>NSAppleEventsUsageDescription</key> 
<string>...this is why I need permission...</string>

看来我的问题(现在)只是使用系统事件的 AppleScripts。尽管确保我的应用程序和osascript 都被允许控制我的计算机(通过安全和隐私> 隐私> 可访问性),但我现在在使用NEAppleScriptosascript 时得到相同的错误(1002)。我的应用程序也被允许控制系统事件(安全和隐私>隐私>自动化)。 osascript 错误在 Xcode 中打印到控制台,我通过使用此代码(在按钮的 @IBAction 中)发现了 NEAppleScript 的错误代码:

let script =
"""
try
    tell application "System Events"
        keystroke "c" using {command down}
    end tell
on error errMsg number errorNumber
    display dialog "An unknown error occurred:  " & errorNumber as text
end try
"""

if let scriptObject = NSAppleScript(source: script) {
    scriptObject.executeAndReturnError(nil)
}

上面的代码导致这个出现在对话框中: An unknown error occurred: 1002

当我的应用程序运行时,它会提示我让它控制系统事件,我总是这样做。我的应用程序没有沙盒化。我相信NSAppleScriptoascript 确实 都为我工作过一次,但是当我再次运行该应用程序时停止工作(尽管我没有对我的代码进行任何更改,但我几乎是肯定的)。

我不知道这是否提供信息,但我对可能发生的事情的唯一其他线索是,我必须不断检查和取消选中 security &amp; privacy &gt; privacy &gt; accessibility 中的脚本编辑器的权限才能让它运行这些 AppleScript因为它告诉我不允许脚本编辑器发送击键。

【问题讨论】:

  • 如果应用被沙盒化,您将无法使用Process 运行脚本。
  • 好点。但是,我的应用没有沙盒化。
  • 您是否在 Info.plist 中添加了NSAppleEventsUsageDescription?顺便说一句,为什么不使用NSAppleScript 运行脚本而不是执行shell 绕行。
  • 请您提供更多上下文。为什么需要模拟command-tab?在我看来,有比通过 osascript 运行 AppleScript 更简单、更有效的方法来实现这一点。 (无论如何,还有更好的方法来运行苹果脚本,比如 NSAppleScript)。但在我知道上下文之前,我无法真正说出。
  • @vadian,我刚刚把它扔进了 Info.plist:&lt;key&gt;NSAppleEventsUsageDescription&lt;/key&gt; &lt;string&gt;NSApplication&lt;/string&gt;。这是添加它的正确方法吗? (我对此还是很陌生。)我正在研究使用 NSAppleScript。

标签: swift macos permissions applescript keystroke


【解决方案1】:

修复osascript 1002 permission issue.

转到安全和隐私 -> 隐私选项卡 -> 辅助功能 -> 添加 osascript (/usr/bin/osascript)

或使用NSAppleScript

【讨论】:

  • 完美运行。谢谢!如果其他人有同样的问题,为了添加osascript,我在终端导航到它的目录并使用open . 在finder 中查看目录。然后,您可以将文件从该查找器窗口拖到当您单击@Parag Bafna 提到的系统首选项位置中的+ 时弹出的窗口中。
  • 更新: 这在我第一次运行代码时有效,但之后停止工作(我实际上只是停止了应用程序并重新启动它)。我现在得到同样的错误,即使osascript 仍然显示它有权控制我的计算机。想法?
  • 您看到在辅助功能中选择了应用还是未选中?
  • 在安全和隐私 -> 隐私选项卡 -> 辅助功能中,我的应用已被选中。在安全和隐私 -> 隐私选项卡 -> 自动化中,它有权控制 Spotify、系统事件和自身(切换最后一个开关无效)。
【解决方案2】:
Security & Privacy -> Privacy tab -> Accessibility

添加 /usr/bin/osascript

注意:您可能还需要添加终端(在我的情况下为 iTerm)

【讨论】:

    【解决方案3】:

    这是您需要考虑的几件事,而不是您问题的真正答案。如果您想了解更多详细信息,我很乐意应要求对其进行编辑。 (另外,我会把代码示例放在 Objective-C 中,因为我还在学习 swift)

    首先,如果您要在应用程序中编写大量脚本,那么切换到Scripting Bridge 可能是值得的。 Scripting Bridge 是一个用于编写其他应用程序的可可接口,因此(借用我在其他地方找到的一个示例)如果您想在 iTunes 中获取当前曲目的名称,您可以执行以下操作:

    iTuneApplication *iTunes = [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"];
    currentTrack = iTunes.currentTrack.name;
    

    如果您想要 Spotify 的特定代码,我必须安装该应用;告诉我。

    其次,如果你想做击键,你应该查看Quartz Event Services。 QES 允许您创建、发送和捕获输入事件。所以如果你想发送一个⌘C,你可以这样做:

    // '8' is the key code for 'c'
    comCDownEvent = CGEventCreateKeyboardEvent(nil, 8, true); 
    CGEventSetFlags(comCDownEvent, kCGEventFlagMaskCommand);
    comCUpEvent = CGEventCreateKeyboardEvent(nil, 8, false); 
    CGEventSetFlags(comCUpEvent, kCGEventFlagMaskCommand);
    CGEventPostToPSN(targetAppProcessSerialNumber, comCDownEvent);
    CGEventPostToPSN(targetAppProcessSerialNumber, comCUpEvent);
    

    您无法从沙盒应用程序中运行此代码,但我认为无论如何您都会遇到这个问题。

    这些方法的主要优点是它们避免了切换上下文:这一切都由 cocoa 完成,因此您无需调用 shell 或创建 AppleScript 环境,并避免了所有涉及的翻译问题。

    【讨论】:

    • 那么这两个例子都在 Objective-C 中?
    • 是的。我不确定第二种情况有多大不同,我想。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-14
    相关资源
    最近更新 更多