AppleScript - 迭代所有打开的应用程序/进程并执行菜单命令
AppleScript - Iterate all open applications / process and execute a menu command
我正在尝试在 MacOS 的 Keyboard Maestro 中编写一个由热键触发的 AppleScript
我想做的,请不要建议任何其他,例如隐藏所有,或隐藏功能。我正在寻找最小化所有打开windows功能,包括动画。
我已经可以全部隐藏了。
所以我想做的是iterate all open windows, trigger 菜单选项 Window -> 最小化 或者如果可能的话以不同的方式触发最小化。
这是我目前所拥有的,但还没有完全发挥作用,只是部分发挥作用:
tell application "System Events"
set currentProcesses to name of every application process whose visible = true
end tell
repeat with tmpProcess in currentProcesses
tell application "System Events" to tell process tmpProcess
set frontmost to true
---activate
tell menu bar item "Window" of menu bar 1
click menu item "Minimize" of menu 1
end tell
end tell
delay 1
end repeat
请注意,某些应用程序的 Minimise 没有用于最小化的 z。。如果解决方案触发了一些全局最小化操作 而不是 而不是通过 菜单 系统 ,那将会很好。
我相信我至少能够从上面的版本中获得一个工作版本。
我想当菜单最小化不存在时我遇到了一些错误,所以我为此添加了 try catch 和一个回退隐藏。
此脚本应该有效:
tell application "System Events"
set currentProcesses to name of every application process whose visible = true
end tell
repeat with tmpProcess in currentProcesses
tell application "System Events" to tell process tmpProcess
set frontmost to true
try
tell menu bar item "Window" of menu bar 1
try
click menu item "Minimize" of menu 1
on error
try
click menu item "Minimise" of menu 1
on error
--- Optional, fallback
set visible to false
end try
end try
end tell
on error
--- Optional, fallback
set visible to false
end try
end tell
delay 0.005
end repeat
网上找到的另一种较慢的解决方案:
tell application "System Events"
repeat with appProc in (every application process whose visible is true)
click (first button of every window of appProc whose role description is "minimize button")
end repeat
end tell
这是我对你提出的问题的原始答案,据说应该适用于相当新的(ish)版本的 MacOS:
use application "System Events"
set _P to a reference to (every process whose class of windows contains window)
set _W to a reference to (windows of _P whose value of attribute "AXMinimized" is false)
set value of attribute "AXMinimized" of _W to true
我可以补充的是,如果我们将每个变量的值插入到引用它的下一行,并且(为简单起见)选择忽略对进程和 windows 使用的过滤,很明显,这四行将在编译时评估这一行代码:
tell application "System Events" to set value of attribute "AXMinimized" of windows of processes to false
但是,您(OP)报告说它很慢而且并不总是可靠,并且可能没有使用迭代方法而是使用递归方法。
我正在等待上述脚本不可靠的详细情况。
你问我是否可以生成 similarly-iterative nature/structure 到 的代码。
这是将我的原始脚本的功能与您的代码结构相结合的脚本:
use application "System Events"
get the name of every application process whose class of windows contains window
repeat with P in the result
get (every window of process (contents of P) whose value of attribute "AXMinimized" is false)
repeat with W in the result
set the value of attribute "AXMinimized" of (contents of W) to true
end repeat
end repeat
正如您的脚本所做的那样,此处的脚本明确地遍历针对过滤器检索的所有应用程序进程(您的过滤器是 属性 visible
每个 process
,而我的过滤器是每个 process
的 window
个对象的集合。如果您觉得有必要,您可以自由更改。
但是,一旦进入遍历 processes
的 repeat
循环,您的脚本忽略的是遍历属于每个进程的每个 window。这就是为什么您需要将 visible
属性 设置为 false
的回退语句的原因,这只是隐藏了应用程序进程(您在 OP 中明确声明您所做的事情 不想想做)。
没有设置 visible
属性,执行的唯一其他操作是为每个进程单击 Minimize
菜单项 一次 。这将触发该应用程序进程的 front window(即当前具有焦点的那个)最小化,但属于它的所有其他 windows 保持不受影响,这意味着每个应用程序进程只有 一个 window 将被最小化。其余的都被可见性切换隐藏了。
对此的补救措施是设置第二个 repeat
循环嵌套在第一个循环中,它遍历针对过滤器检索的特定进程的所有 windows(与以前一样,我选的是AXMinimized
属性)。
那么只需将每个window的AXMinimized
属性设置为true
即可。
正如您所指出的,您的脚本的一个优点是它似乎比我的更快地最小化 windows。据我所知,由于 某些 原因,实际最小化 animation 在使用菜单触发时比通过属性值的设置。所以我继续创建了一个脚本,它不会尝试设置 windows 的属性,而是使用您单击 Minimize
菜单项的机制:
use application "System Events"
set _P to a reference to (every application process whose visible is true)
repeat with P in (_P as list)
set frontmost of P to true
set _M to (a reference to menu 1 of menu bar item "Window" of menu bar 1 of P)
set _minimise to (a reference to menu item "Minimise" of _M)
set _minimize to (a reference to menu item "Minimize" of _M)
set _W to windows of P
set n to count _W
if n > 0 then perform action "AXRaise" of _W's front item
repeat n times
if (_minimize exists) and (_minimize is enabled) then
click _minimize
else if (_minimise exists) and (_minimise is enabled) then
click _minimise
end if
end repeat
end repeat
此脚本本质上是您的修改版,对其进程使用相同的过滤条件 (whose visible is false
) 并单击菜单项 Minimize
(或 Minimise
)以最小化windows。它包含 processes
的外部 repeat
循环和 windows
.
的内部 repeat
循环
老实说,很难说哪个似乎比另一个更迅速地最小化 windows,所以我会让你来判断。
但是,回想起您在最初的简报中所说的内容,您特别询问:
- 对于一个"global minimize action rather than [to] go through the menu system";
- 不提供其他建议"such as 'hide all', or 'hide' functionality. I am looking for [a] 'minimize-all-open-windows' functionality";
- 到[包括]动画。
坦率地说,仍然只有一个解决方案满足所有这些条件,这就是我发布的原始答案。您发现的其他解决方案要么不起作用,要么依赖于隐藏应用程序 windows;我在上面提供的最后一个贡献有效,但使用了菜单项,这不是您理想的方法;和之前的脚本,它首先演示了两个 repeat
循环的嵌套以遍历两个过程 和 windows 可以通过归纳推理证明是与我的原始解决方案相同的脚本,尽管没有您习惯于在编程语言中看到的显式迭代语句, 仍然会遍历 process
和 window
幕后对象。
当然,您可以选择任何您想要的方法,因为您的项目和您的最终满意度对于创建您将成为 day-to-day 中使用的工具的工具很重要。但是,为了就实现你打算做的事情的最佳方法给出我的诚实和最终意见,我强烈建议你选择我第一个答案的紧凑形式,这是非常优雅和简单的代码行:
tell application "System Events" to set value of attribute "AXMinimized" of windows of processes to false
另一个工作示例,迄今为止最好的。
tell application "System Events"
set currentProcesses to name of every application process whose visible = true
end tell
repeat with tmpProcess in currentProcesses
tell application "System Events" to tell process tmpProcess
set frontmost to true
try
tell menu bar item "Window" of menu bar 1
try
click menu item "Minimize" of menu 1
on error
try
click menu item "Minimise" of menu 1
end try
end try
end tell
end try
delay 0.1
set visible to false
end tell
end repeat
我正在尝试在 MacOS 的 Keyboard Maestro 中编写一个由热键触发的 AppleScript
我想做的,请不要建议任何其他,例如隐藏所有,或隐藏功能。我正在寻找最小化所有打开windows功能,包括动画。
我已经可以全部隐藏了。
所以我想做的是iterate all open windows, trigger 菜单选项 Window -> 最小化 或者如果可能的话以不同的方式触发最小化。
这是我目前所拥有的,但还没有完全发挥作用,只是部分发挥作用:
tell application "System Events"
set currentProcesses to name of every application process whose visible = true
end tell
repeat with tmpProcess in currentProcesses
tell application "System Events" to tell process tmpProcess
set frontmost to true
---activate
tell menu bar item "Window" of menu bar 1
click menu item "Minimize" of menu 1
end tell
end tell
delay 1
end repeat
请注意,某些应用程序的 Minimise 没有用于最小化的 z。。如果解决方案触发了一些全局最小化操作 而不是 而不是通过 菜单 系统 ,那将会很好。
我相信我至少能够从上面的版本中获得一个工作版本。
我想当菜单最小化不存在时我遇到了一些错误,所以我为此添加了 try catch 和一个回退隐藏。
此脚本应该有效:
tell application "System Events"
set currentProcesses to name of every application process whose visible = true
end tell
repeat with tmpProcess in currentProcesses
tell application "System Events" to tell process tmpProcess
set frontmost to true
try
tell menu bar item "Window" of menu bar 1
try
click menu item "Minimize" of menu 1
on error
try
click menu item "Minimise" of menu 1
on error
--- Optional, fallback
set visible to false
end try
end try
end tell
on error
--- Optional, fallback
set visible to false
end try
end tell
delay 0.005
end repeat
网上找到的另一种较慢的解决方案:
tell application "System Events"
repeat with appProc in (every application process whose visible is true)
click (first button of every window of appProc whose role description is "minimize button")
end repeat
end tell
这是我对你提出的问题的原始答案,据说应该适用于相当新的(ish)版本的 MacOS:
use application "System Events"
set _P to a reference to (every process whose class of windows contains window)
set _W to a reference to (windows of _P whose value of attribute "AXMinimized" is false)
set value of attribute "AXMinimized" of _W to true
我可以补充的是,如果我们将每个变量的值插入到引用它的下一行,并且(为简单起见)选择忽略对进程和 windows 使用的过滤,很明显,这四行将在编译时评估这一行代码:
tell application "System Events" to set value of attribute "AXMinimized" of windows of processes to false
但是,您(OP)报告说它很慢而且并不总是可靠,并且可能没有使用迭代方法而是使用递归方法。
我正在等待上述脚本不可靠的详细情况。
你问我是否可以生成 similarly-iterative nature/structure 到
这是将我的原始脚本的功能与您的代码结构相结合的脚本:
use application "System Events"
get the name of every application process whose class of windows contains window
repeat with P in the result
get (every window of process (contents of P) whose value of attribute "AXMinimized" is false)
repeat with W in the result
set the value of attribute "AXMinimized" of (contents of W) to true
end repeat
end repeat
正如您的脚本所做的那样,此处的脚本明确地遍历针对过滤器检索的所有应用程序进程(您的过滤器是 属性 visible
每个 process
,而我的过滤器是每个 process
的 window
个对象的集合。如果您觉得有必要,您可以自由更改。
但是,一旦进入遍历 processes
的 repeat
循环,您的脚本忽略的是遍历属于每个进程的每个 window。这就是为什么您需要将 visible
属性 设置为 false
的回退语句的原因,这只是隐藏了应用程序进程(您在 OP 中明确声明您所做的事情 不想想做)。
没有设置 visible
属性,执行的唯一其他操作是为每个进程单击 Minimize
菜单项 一次 。这将触发该应用程序进程的 front window(即当前具有焦点的那个)最小化,但属于它的所有其他 windows 保持不受影响,这意味着每个应用程序进程只有 一个 window 将被最小化。其余的都被可见性切换隐藏了。
对此的补救措施是设置第二个 repeat
循环嵌套在第一个循环中,它遍历针对过滤器检索的特定进程的所有 windows(与以前一样,我选的是AXMinimized
属性)。
那么只需将每个window的AXMinimized
属性设置为true
即可。
正如您所指出的,您的脚本的一个优点是它似乎比我的更快地最小化 windows。据我所知,由于 某些 原因,实际最小化 animation 在使用菜单触发时比通过属性值的设置。所以我继续创建了一个脚本,它不会尝试设置 windows 的属性,而是使用您单击 Minimize
菜单项的机制:
use application "System Events"
set _P to a reference to (every application process whose visible is true)
repeat with P in (_P as list)
set frontmost of P to true
set _M to (a reference to menu 1 of menu bar item "Window" of menu bar 1 of P)
set _minimise to (a reference to menu item "Minimise" of _M)
set _minimize to (a reference to menu item "Minimize" of _M)
set _W to windows of P
set n to count _W
if n > 0 then perform action "AXRaise" of _W's front item
repeat n times
if (_minimize exists) and (_minimize is enabled) then
click _minimize
else if (_minimise exists) and (_minimise is enabled) then
click _minimise
end if
end repeat
end repeat
此脚本本质上是您的修改版,对其进程使用相同的过滤条件 (whose visible is false
) 并单击菜单项 Minimize
(或 Minimise
)以最小化windows。它包含 processes
的外部 repeat
循环和 windows
.
repeat
循环
老实说,很难说哪个似乎比另一个更迅速地最小化 windows,所以我会让你来判断。
但是,回想起您在最初的简报中所说的内容,您特别询问:
- 对于一个"global minimize action rather than [to] go through the menu system";
- 不提供其他建议"such as 'hide all', or 'hide' functionality. I am looking for [a] 'minimize-all-open-windows' functionality";
- 到[包括]动画。
坦率地说,仍然只有一个解决方案满足所有这些条件,这就是我发布的原始答案。您发现的其他解决方案要么不起作用,要么依赖于隐藏应用程序 windows;我在上面提供的最后一个贡献有效,但使用了菜单项,这不是您理想的方法;和之前的脚本,它首先演示了两个 repeat
循环的嵌套以遍历两个过程 和 windows 可以通过归纳推理证明是与我的原始解决方案相同的脚本,尽管没有您习惯于在编程语言中看到的显式迭代语句, 仍然会遍历 process
和 window
幕后对象。
当然,您可以选择任何您想要的方法,因为您的项目和您的最终满意度对于创建您将成为 day-to-day 中使用的工具的工具很重要。但是,为了就实现你打算做的事情的最佳方法给出我的诚实和最终意见,我强烈建议你选择我第一个答案的紧凑形式,这是非常优雅和简单的代码行:
tell application "System Events" to set value of attribute "AXMinimized" of windows of processes to false
另一个工作示例,迄今为止最好的。
tell application "System Events"
set currentProcesses to name of every application process whose visible = true
end tell
repeat with tmpProcess in currentProcesses
tell application "System Events" to tell process tmpProcess
set frontmost to true
try
tell menu bar item "Window" of menu bar 1
try
click menu item "Minimize" of menu 1
on error
try
click menu item "Minimise" of menu 1
end try
end try
end tell
end try
delay 0.1
set visible to false
end tell
end repeat