macos AppleScript 或 Automator 用于单击应用程序中的菜单?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2111736/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 06:41:38  来源:igfitidea点击:

AppleScript or Automator to click on menus in an application?

macosapplescriptautomatorexcel-2008

提问by user141146

I'm not sure if this is do-able via AppleScript and/or Automator…but I'd like to be able to:

我不确定这是否可以通过 AppleScript 和/或 Automator 实现……但我希望能够:

a) launch an application (I know this can be done pretty easily by AppleScript or Automator)

a) 启动一个应用程序(我知道这可以通过 AppleScript 或 Automator 轻松完成)

b) once the application is launched, use AppleScript or Automator to select specific menu items.

b) 应用程序启动后,使用 AppleScript 或 Automator 选择特定菜单项。

e.g. I'd like to launch Excel 2008 (I have the home/student edition which doesn't come preconfigured for Automator) and then click the "File" menu and click on "open".

例如,我想启动 Excel 2008(我有没有为 Automator 预先配置的家庭/学生版),然后单击“文件”菜单并单击“打开”。

Any pointers on where to go/look for how to select menu items like this (or if it's even possible at all)?

关于去哪里/寻找如何选择这样的菜单项(或者甚至可能)的任何指示?

You can "sort of" do this using Automator's Record function, but Record is very brittle.

您可以使用 Automator 的 Record 功能“有点”做到这一点,但 Record 非常脆弱。

I'd rather be able to use AppleScript to simply grab an "array" that contains every menu item for the application and then programmatically click on the 0th menu item in my array…etc. etc.

我宁愿能够使用 AppleScript 来简单地获取一个“数组”,其中包含应用程序的每个菜单项,然后以编程方式单击我的数组中的第 0 个菜单项……等等。等等。

Is this possible?

这可能吗?

TIA

TIA

采纳答案by Peter Loron

I don't know about grabbing an array, but this looks like it might work for sending the mouse clicks, etc:

我不知道如何抓取数组,但这看起来可能适用于发送鼠标点击等:

VirtualInput

虚拟输入

回答by VaginalDragon

tell application "###"

activate

end tell


tell application "System Events"

tell process "###"

click menu item "^^^" of menu "$$$" of menu bar 1

end tell

end tell

Put your application in for the ### and put your menu item in for the ^^^ and put your menu (file, edit, view, etc.) in for $$$. Capitalization matters.

将您的应用程序放入### 并将您的菜单项放入^^^ 并将您的菜单(文件、编辑、查看等)放入$$$。资本化问题。

Put it in applescript btw

顺便说一句,把它放在applescript中

EXAMPLE:

例子:

tell application "iTunes"

activate

end tell


tell application "System Events"

tell process "iTunes"

click menu item "as list" of menu "view" of menu bar 1

end tell

end tell

delete the double spaces EXCEPT BETWEEN END TELL AND TELL APPLICATION "SYSTEM EVENTS"

删除除 END TELL 和 TELL 应用程序“系统事件”之外的双空格

回答by Barry Wark

UI scripting is a fickle beast. It's brittle and often sensitive to many things beyond your control such as unexpected dialogs (from other applications), changes in system font or language, user activity. Not to mention changes in an application's UI across versions.

UI 脚本是一个善变的野兽。它很脆弱,而且通常对许多您无法控制的事情很敏感,例如意外的对话框(来自其他应用程序)、系统字体或语言的更改、用户活动。更不用说跨版本应用程序 UI 的变化了。

It's much more robust to use talk directly to the application via its AppleScript API. This is exactly the purpose of AppleScript. You can always see the actions and data an application can provide via AppleScript via the "Open Dictionary..." menu item in AppleScript Editor.app's (select the application you want to script in the file dialog). Instead of simulating a mouse click on a menu, you call the action that menu item triggers directly via AppleScript.

通过 AppleScript API 直接与应用程序对话要健壮得多。这正是 AppleScript 的目的。您始终可以通过 AppleScript Editor.app 中的“打开词典...”菜单项(在文件对话框中选择要编写脚本的应用程序)查看应用程序可以通过 AppleScript 提供的操作和数据。您不是模拟鼠标单击菜单,而是直接通过 AppleScript 调用菜单项触发的操作。

Of course not all applications have a complete (or even any) AppleScript API. Excel, however, has excellent AppleScript support, if that's your target.

当然,并非所有应用程序都有完整的(甚至任何)AppleScript API。但是,Excel 具有出色的 AppleScript 支持,如果这是您的目标的话。

If you're really trying to do UI testing, I recommend you start with other options:

如果您真的想进行 UI 测试,我建议您从其他选项开始:

  1. Test the model (analogous to scripting the app's model via AppleScript). In fact, if you include an AppleScript API in your app, you can automated testing of that API as well.
  2. Use Google Toolbox for Mac'sunit testing additions (or roll your own) to programatically send mouse or keyboard events to your app.
  3. Use Instruments.app to record a UI sequence. The Instruments recording is solid (I haven't used Automator's Record feature), and you get all the other goodies of Instruments too.
  1. 测试模型(类似于通过 AppleScript 编写应用程序模型的脚本)。事实上,如果您在应用程序中包含 AppleScript API,您也可以自动测试该 API。
  2. 使用Google Toolbox for Mac 的单元测试添加(或自行推出)以编程方式将鼠标或键盘事件发送到您的应用程序。
  3. 使用 Instruments.app 记录一个 UI 序列。Instruments 录音是可靠的(我没有使用 Automator 的 Record 功能),您也可以获得 Instruments 的所有其他优点。

回答by Doug Grinbergs

Indeed, UI scripting is fragile and finicky, but you might take a look at Apple's AppleScript GUI Scripting page

确实,UI 脚本编写是脆弱和挑剔的,但您可以查看 Apple 的AppleScript GUI 脚本页面

回答by LennyR

I frequently need to create a GUI script to access a menu item in applications whose AppleScript library doesn't provide direct access to the objects or functions the menu item represents. To make it easy to re-use the code, I use variables for the app, menu, & menu item names. Then I just need to change the variables at the top rather than pick out the names from the code body.

我经常需要创建一个 GUI 脚本来访问应用程序中的菜单项,这些应用程序的 AppleScript 库不提供对菜单项所代表的对象或功能的直接访问。为了便于重用代码,我使用了应用程序、菜单和菜单项名称的变量。然后我只需要更改顶部的变量而不是从代码体中挑选名称。

set targetApp to "app_name"
set theMenu to "menu_name"
set theItem to "menu_item_name"

tell application targetApp
    activate
    tell application "System Events"
        tell application process targetApp
            tell menu bar 1
                tell menu bar item theMenu
                    tell menu theMenu
                        click menu item theItem
                    end tell
                end tell
            end tell
        end tell
    end tell
end tell

SUB-MENUS

子菜单

It gets a little more involved when there are sub- & sub-sub-menus involved, as a menu item with a sub-menu is both a menu item of its parent menu AND a menu parent of its sub-menus. Note that the text variable "theItem" is used to specify both a menu item AND a menu; the "targetApp" string variable is used to reference both an app & a process, so it saves having to edit 2 names in 2 places each when reusing the code. I use this script to run on voice commands for accessing menu items quickly rather than having to say, e.g., "click Edit Menu"... "click Transformations"... "click Make Upper Case"... I add another variable for the sub-menu item:

当涉及到子菜单和子子菜单时,它会变得更加复杂,因为带有子菜单的菜单项既是其父菜单的菜单项,又是其子菜单的父菜单。请注意,文本变量“theItem”用于指定菜单项和菜单;“targetApp”字符串变量用于引用应用程序和进程,因此在重用代码时无需在 2 个位置分别编辑 2 个名称。我使用此脚本运行语音命令以快速访问菜单项,而不必说,例如,“单击编辑菜单”...“单击转换”...“单击制作大写”...我添加了另一个变量对于子菜单项:

set targetApp to "app_name"
set theMenu to "menu_name"
set theItem to "menu_item_name"
set theSubItem to "sub_item_name"

tell application targetApp
    activate
    tell application "System Events"
        tell application process targetApp
            tell menu bar 1
                tell menu bar item theMenu
                    tell menu theMenu
                        tell menu item theItem
                            tell menu theItem
                                click menu item theSubItem
                            end tell
                        end tell
                    end tell
                end tell
            end tell
        end tell
    end tell
end tell

For example:

例如:

set targetApp to "TextEdit"
set theMenu to "Edit"
set theItem to "Transformations"
set theSubItem to "Make Upper Case"

tell application targetApp
    activate
    tell application "System Events"
        tell application process targetApp
            tell menu bar 1
                tell menu bar item theMenu
                    tell menu theMenu
                        tell menu item theItem
                            tell menu theItem
                                click menu item theSubItem
                            end tell
                        end tell
                    end tell
                end tell
            end tell
        end tell
    end tell
end tell

If there's another level of sub-menus, an additional variable (e.g., "theSubSubItem") would be required, & the line in the System Events process tell block would have another layer
...

如果有另一个级别的子菜单,则需要一个额外的变量(例如,“theSubSubItem”),并且系统事件过程中的行告诉块将有另一层
......

                            tell menu item theItem
                                tell menu theSubItem
                                    click menu item theSubSubItem
                                end tell
                            end tell

...
As noted elsewhere in this thread it's recommended to address an application's objects & functions directly whenever they're included in the API, but addressing the GUI is useful as a last resort when the API doesn't provide direct access. The downside is a GUI script can get more cumbersome & may have to be revised with each application update.

...
正如本线程中的其他地方所述,建议在 API 中包含应用程序的对象和函数时直接对其进行寻址,但是当 API 不提供直接访问时,寻址 GUI 作为最后的手段很有用。缺点是 GUI 脚本可能会变得更麻烦,并且每次应用程序更新时都可能需要进行修改。