AppleScript:获取所有桌面上的窗口列表

时间:2013-12-12 21:26:47

标签: user-interface automation window applescript osx-lion

我需要计算每个应用程序的所有窗口数。我试图这样做的每一种方式,我只得到分配给当前(任务控制)桌面的窗口数。 (我目前正在运行Mac OS X 10.7,所以后空格。)有没有办法在所有桌面上获得所有窗口的每个应用程序数量?

我尝试过的关键:

tell application "System Events"
  repeat with _app in (every process whose visible is true)
    tell _app
      log (name as string) & ": " & (count of every window)
    end tell
  end repeat
end tell

请注意,whose visible is true子句不是问题。它找到了所有适当的进程,但是一旦我询问了windows的进程,它们只计算活动桌面中的进程。

我尝试将log行从tell中拉出来并使用name of _appcount of every window of _app,但没有区别。我尝试从process中抓取除System Events es以外的其他内容,但任何有用的内容最终都会有效地成为获取同一对象的另一种方式。我已尝试迭代UI elements,但没有显示当前桌面上没有的窗口,但我确实为每个应用程序获取了一个菜单栏。

我很好地迭代所有桌面(虽然实际上没有切换到所有桌面),但我甚至找不到获取桌面列表的方法。 This answer声称如何做到这一点,但我只在every desktop内获得了一个元素。并不是说,无论如何都有一个明显的方法来获取Windows桌面对象。

值得指出的是台式机是由Dock控制的,而不是由Mission Control控制的。我不知道AppleScript有什么方法可以与Dock通信,所以如果你知道某些事情,那么对此的回答或评论可能会帮助我指出正确的方向。

我想做一些不可能的事吗?

2 个答案:

答案 0 :(得分:0)

我运行了您的代码,将 Applescript 版本设置为 2.4(习惯性地这样做);在第一次运行时,您的代码向我显示了每个应用程序所有窗口的适当数量。

这段代码是我试过的,结果似乎还算满意。有什么我没看到的吗?

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions


tell application "System Events"
    set my_list to {}
    repeat with _app in (every process whose visible is true)
        tell _app
            log (name as string) & ": " & (count of every window)
            set my_list to my_list & {name as string, count of every window}
        end tell
    end repeat
    log my_list
end tell

答案 1 :(得分:0)

由于 OP 已超过 6 年,我无法在 OS X 10.7 下进行测试,这是当时使用的,但是,以下示例 AppleScript 代码ma​​cOS Catalina 下为我工作并返回正确的窗口计数跨所有桌面/空间,除了任何应用程序,它理解给定的AppleScript命令以及为什么正在使用 tryon error statements

示例 AppleScript 代码

tell application "System Events" to ¬
    set appBundleIdentifierList to ¬
        the bundle identifier of ¬
            (every process whose visible is true)

repeat with appBundleIdentifier in appBundleIdentifierList
    try
        tell application id appBundleIdentifier to ¬
            set {appName, winCount} to {name, (count windows)}
        log appName & ": " & winCount
    on error errorMessage
        log errorMessage
    end try
end repeat

示例输出在我的系统上有多个桌面/空间应用程序窗口,或者某些桌面/空间和每个窗口计数在所有桌面/空间中都是正确的,而不仅仅是活动的桌面/空间脚本是从中运行的。

(*Safari: 6*)
(*Terminal: 2*)
(*TextEdit: 4*)
(*Script Editor: 7*)
(*Finder: 3*)
(*BBEdit: 1*)
(*Norton Secure VPN got an error: every window doesn’t understand the “count” message.*)
(*Music: 2*)

注意事项:

并非所有应用程序都可以AppleScript脚本化,因为有些应用程序在它们的AppleScript字典中不包含AppleScript字典 em>应用程序包。

由于 application process 无法在所有桌面/空间中返回正确数量的窗口,因此此方法依赖于 application 返回所有桌面/空间窗口数量。



更新:

以下示例 AppleScript 代码执行以下操作:

  • 获取每个可见为 true 的进程的包标识符。

  • 对于每个包标识符,通过直接查询应用程序来获取它的名称窗口计数。

    如果应用程序理解AppleScript命令,那么如果进入下一个项目appBundleIdentifierList 列表中。

    如果它不明白,那么窗口计数由以下计算:

    • 尝试获得不可见的窗口算作,因为它们不会出现在应用程序窗口菜单上。
    • 根据应用程序窗口菜单上显示的窗口数计算窗口计数。
    • 如果这些方法失败,它会通过查询应用程序进程来获取窗口计数,只有活动的桌面/空间才是准确的,并且是包括仅用于尝试使用 basic vanilla AppleScript 来确定 window 计数的完整性。
    • 转到appBundleIdentifierList列表中的应用程序

示例 AppleScript 代码

set menuName to "Window"

tell application id "com.apple.systemevents" to ¬
    set appBundleIdentifierList to ¬
        the bundle identifier of ¬
            (every process whose visible is true)

repeat with appBundleIdentifier in appBundleIdentifierList
    try
        tell application id appBundleIdentifier to ¬
            set {appName, winCount} to {name, (count windows)}
        log appName & ": " & winCount & ¬
            " -- By querying the application directly."
    on error
        set winCount to 0
        set notVisibleWindowList to {}
        set errAppName to ¬
            name of application id appBundleIdentifier
        tell application id "com.apple.systemevents"
            try
                tell application process errAppName
                    set notVisibleWindowList to ¬
                        (windows whose visible is false)
                    if notVisibleWindowList is {} then ¬
                        set winCount to ¬
                            length of notVisibleWindowList
                end tell
            end try
            try
                set theTargetMenuItemsList to ¬
                    the reverse of ¬
                        (get name of ¬
                            menu items of ¬
                            menu menuName of ¬
                            menu bar item menuName of ¬
                            menu bar 1 of ¬
                            application process errAppName)
            on error
                set theTargetMenuItemsList to {}
            end try
        end tell
        if theTargetMenuItemsList is not {} then
            repeat with anItem in theTargetMenuItemsList
                if contents of anItem is ¬
                    missing value then exit repeat
                set winCount to winCount + 1
            end repeat
            log errAppName & ": " & winCount & ¬
                " -- By querying the Window menu of the application process."
        else
            try
                tell application id "com.apple.systemevents" to ¬
                    set winCount to ¬
                        (count windows of ¬
                            application process errAppName)
                log errAppName & ": " & winCount & ¬
                    " -- By querying the application process. " & ¬
                    "May not be accurate, verify as necessary."
            end try
        end if
    end try
end repeat

运行两个版本的示例 AppleScript 代码以显示输出的差异:

第一版示例 AppleScript 代码

(*Safari: 6*)
(*TextEdit: 4*)
(*Finder: 3*)
(*BBEdit: 1*)
(*Norton Secure VPN got an error: every window doesn’t understand the “count” message.*)
(*Music: 2*)
(*Sublime Text 2 got an error: every window doesn’t understand the “count” message.*)
(*DiskCatalogMaker got an error: every window doesn’t understand the “count” message.*)
(*Script Editor: 7*)
(*System Preferences: 2*)
(*VMware Fusion got an error: every window doesn’t understand the “count” message.*)
(*Activity Monitor got an error: every window doesn’t understand the “count” message.*)
(*Terminal: 2*)

第二个版本example AppleScript 代码

(*Safari: 6 -- By querying the application directly.*)
(*TextEdit: 4 -- By querying the application directly.*)
(*Finder: 3 -- By querying the application directly.*)
(*BBEdit: 1 -- By querying the application directly.*)
(*Norton Secure VPN: 0 -- By querying the application process. May not be accurate, verify as necessary.*)
(*Music: 2 -- By querying the application directly.*)
(*Sublime Text 2: 4 -- By querying the Window menu of the application process.*)
(*DiskCatalogMaker: 2 -- By querying the Window menu of the application process.*)
(*Script Editor: 7 -- By querying the application directly.*)
(*System Preferences: 2 -- By querying the application directly.*)
(*VMware Fusion: 1 -- By querying the Window menu of the application process.*)
(*Activity Monitor: 0 -- By querying the Window menu of the application process.*)
(*Terminal: 2 -- By querying the application directly.*)

正如您所看到的,即使 Activity Monitor(本机默认的 ma​​cOS 应用程序),窗口 菜单也必须由于应用程序直接不理解基本的count windows AppleScript 命令而被查询。

尽管第二版代码的输出在执行时在所有桌面/空间中都是准确的,但任何应用有“通过查询申请流程。可能不准确,必要时核实”。作为其输出的一部分,它只包括它在表单中执行的活动桌面/空间窗口计数。底线是使用basic vanilla AppleScript 无法保证获得每个可见应用程序的完整准确窗口计数> 除非直接查询当时所有的应用。通过应用进程查询窗口菜单也应该是准确的。

话虽如此,我认为可能需要使用其他方法来获得准确的计数。