AppleScript - 迭代所有打开的应用程序/进程并执行菜单命令

时间:2018-03-14 22:41:11

标签: macos macros applescript automator keyboard-maestro

我正在尝试编写一个AppleScript,由MacOS上的Keyboard Maestro中的热键触发

我想做什么,请不要建议 ANYTHING ELSE ,例如隐藏所有,或隐藏功能。我正在寻找最小化所有打开的窗口功能, 包括动画

我已经可以隐藏所有了。

所以我想做的是迭代 所有打开的窗口,触发菜单选项窗口 - >最小化或者如果可能的话,以不同的方式触发最小化。

这是我到目前为止所做的,但它没有完全正常工作,仅部分

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

注意,某些应用程序将使用最小化而不使用z进行最小化。。如果解决方案触发了一些全局最小化操作而非而不是通过菜单 系统,那将会很好。

4 个答案:

答案 0 :(得分:1)

以下是我对您提出的问题的原始答案,该陈述应该适用于MacOS的最新版本( ish ):

    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

我可以添加的是,如果我们将每个变量的值插入到引用它的下一行,并且(为简单起见)选择忽略对进程和窗口使用的过滤,它变为很明显,这四行将在编译时评估这一行代码:

    tell application "System Events" to set value of attribute "AXMinimized" of windows of processes to false

然而,你(OP)报告它很慢并且不总是可靠的,并且可能没有使用迭代方法而是递归方法。

我等待上述脚本被发现不可靠的情况详情。

你问我是否可以为one of your proposed methods生成类似迭代性质/结构的代码。

这是将原始脚本的功能与您的代码结构混合在一起的脚本:

    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,而我的过滤器是每个window的{​​{1}}个对象的集合。如果你觉得有必要,你可以自由改变。

但是,一旦进入遍历process的{​​{1}}循环内,您的脚本忽略的就是遍历属于每个进程的每个窗口。这就是为什么你需要将repeat属性设置为processes的后备语句,这只是隐藏了应用程序进程(你在OP中明确说明了你做过的事情想做)。

如果未设置visible属性,则执行的唯一其他操作是单击每个进程的false菜单项一次。这将触发该应用程序进程的窗口(即当前具有焦点的窗口)以最小化,但属于它的所有其他窗口保持不受影响,这意味着仅一个窗口对于每个申请流程将最小化。其余的都只是通过可见性切换隐藏。

对此的补救措施是设置第二个visible循环嵌套在第一个循环中,循环遍历针对过滤器检索的特定进程的所有窗口(如前所述,我选择成为{ {1}}属性)。

然后,只需将每个窗口的Minimize属性设置为repeat即可。

正如您所指出的,您的脚本的一个优点是它似乎比我的更快地最小化窗口。据我所知,出现一些的原因,实际的最小化动画在使用菜单触发时比通过设置属性值触发时更快。然后我继续创建了一个脚本,它不会尝试设置窗口的属性,而是使用您点击AXMinimized菜单项的机制:

AXMinimized

此脚本本质上是您的重写版本,对其进程使用相同的过滤条件(true)并单击菜单项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的内部repeat循环。

老实说,很难说哪一个看起来比另一个更快地减少了窗口,所以我会让你做出判断。

但是,回想一下您在原始简报中所说的内容,您特别要求:

  • 对于"全局最小化操作,而不是[来]通过菜单系统" ;
  • 不提供其他建议"例如'隐藏所有'或隐藏'功能。我正在寻找[a]'最小化 - 全开窗口'功能" ;
  • " [包含]动画。"

坦率地说,它仍然只有一个满足所有这些标准的解决方案,这就是我发布的原始答案。您发现的其他解决方案要么不工作,要么依赖隐藏应用程序窗口;我上面提供的最后一个贡献,但利用菜单项,这不是你理想的方法;之前的脚本,首先演示了两个processes循环的嵌套,以便遍历两个进程窗口,可以通过归纳推理来演示与我原始解决方案相同的脚本尽管没有明确的迭代语句,你习惯于在编程语言中看到,确实仍然在幕后迭代repeatwindows个对象。

当然,您可以选择您想要的任何方法,因为这是您的项目和您的最终满意度,这对于创建一个您日常使用的工具非常重要。但是,为了对实现你要做的事情的最佳方法给出诚实和最终的意见,我强烈建议你选择我的第一个答案的压缩形式,这是一个非常优雅和简单的代码行:

repeat

答案 1 :(得分:0)

我相信我至少可以从上面的版本中获得一个工作版本。

我认为当菜单最小化不存在时我遇到了一些错误,所以我添加了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

答案 2 :(得分:0)

在线发现另一种较慢的解决方案:

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 

答案 3 :(得分:0)

另一个工作示例,目前为止最好。

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