开发者问题收集

从 macOS 应用程序调用时,使用“密钥代码”的 AppleScript 出现错误 1002

2019-08-24
5628

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

/Users/my_username/Desktop/test_apple_script.scpt:执行错误:系统事件出现错误:不允许 osascript 发送击键。 (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 应用程序运行,就像我在脚本编辑器中运行它一样?

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

编辑: 如果我的原始问题不清楚,显示通知的简单 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>

看来我的问题(现在)只是与使用系统事件的 AppleScript 有关。尽管确保我的应用和 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)
}

上述代码导致对话框中出现此信息: 发生未知错误:1002

当我的应用运行时,它会提示我授予它对系统事件的控制权,而我总是这么做。我的应用没有沙盒化。我相信 NSAppleScriptoascript 都曾经为我工作过一次,但当我再次运行应用时它们就停止工作了(尽管我没有对我的代码进行任何更改,但我几乎可以肯定)。

我不知道这是否有帮助,但我唯一能想到的线索是,我必须不断在 security & privacy > privacy > accessibility 中选中和取消选中脚本编辑器的权限,以使其运行这些 AppleScript,因为它告诉我脚本编辑器不允许发送击键。

3个回答
Security & Privacy -> Privacy tab -> Accessibility

添加 /usr/bin/osascript

NOTE: You may also need to add your terminal (iTerm in my case)

ajthinking
2020-01-25

修复 osascript 1002 权限问题。

转到“安全与隐私”->“隐私”选项卡->“可访问性”->“添加 osascript (/usr/bin/osascript)”

或使用 NSAppleScript

Parag Bafna
2019-08-25

这是供您考虑的几件事,而不是对您的问题的真正回答。如果您想要更多详细信息,我很乐意根据要求进行编辑。(此外,我会在 Objective-C 中放置代码示例,因为我仍在学习 Swift)

首先,如果您要在应用程序中进行大量脚本编写,那么切换到 Scripting Bridge 可能是值得的。Scripting Bridge 是一个用于为其他应用程序编写 AppleScript 的 Cocoa 接口,因此(窃取我在其他地方找到的一个例子)如果您想获取 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 环境,并避免涉及的所有翻译问题。

Ted Wrigley
2019-08-27