作为该
OP已经超过六年了,我无法在当时使用的
OS X 10.7下进行测试,尽管如此,以下
示例AppleScript代码对我来说在
macOS Catalina下运行正常,并在所有
桌面/空间中返回正确的
窗口数量,除了任何能够理解给定的
AppleScript命令以及为什么要使用
try
和
on error
语句。
示例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代码执行以下操作:
获取每个可见进程的捆绑标识符。
对于每个捆绑标识符,通过直接查询应用程序来获取其名称和窗口计数。
如果应用程序理解AppleScript命令,则转到appBundleIdentifierList列表中的下一项。
如果不理解,则按以下方式计算窗口计数:
- 尝试获取不可见窗口计数,因为它们不会显示在应用程序的Window菜单中。
- 通过在应用程序的Window菜单中显示的窗口数量计算窗口计数。
- 如果这些方法失败,则通过查询应用程序进程来获取窗口计数,这只对活动的桌面/空间准确,并且仅包含尝试使用基本vanilla AppleScript确定窗口计数的完整性。
然后转到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*)
第二个版本的示例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.*)
作为一个本地的默认macOS应用程序,即使是Activity Monitor,窗口菜单也必须被查询,因为该应用程序直接不能理解基本的count windows AppleScript命令。尽管第二个版本的代码输出在执行时准确跨越了所有的桌面/空间,但任何具有“通过查询应用程序进程。可能不准确,请根据需要验证。”作为其输出一部分的应用程序只包括从执行的活动桌面/空间的窗口计数。底线是使用基本的vanilla AppleScript,没有保证能够获得每个可见应用程序的完整准确的窗口计数,除非可以直接查询所有应用程序。通过其应用程序进程查询窗口菜单也应该是准确的。
话虽如此,我认为可能需要使用其他方法来获得准确的计数。
strings ~/Library/Preferences/com.apple.spaces.plist
返回(任意)一组包含每个桌面和监视器的连续UID集群,因此可以通过减去显示器数量并再次添加1来确定桌面数量以获取主显示器(或者,如果没有辅助显示器,则仅为每个桌面返回非连续UID)。还有一个假设是每个全屏应用程序都会获得一个桌面UID。 - hepcat72