从我能找到的所有API文档中,似乎正确的做法是检查System Events返回的"最前面"窗口或API的可访问性,就像这样(这里是Python中的示例,但这在ObjC或swift或ruby中是相同的):
#!/usr/bin/env python
from ScriptingBridge import SBApplication
events = SBApplication.applicationWithBundleIdentifier_(
"com.apple.systemevents")
for proc in events.applicationProcesses():
if proc.frontmost():
print(proc.name())
我从中得到的值与从NSWorkspace.sharedWorkspace().frontmostApplication()
得到的值相同。它通常是正确的。除非提示对话框,尤其是来自系统的对话框,实际上是键盘焦点所在的。例如,如果Messages.app想要我的Jabber帐户的密码,或者如果我的iCloud密码更改;这些对话框似乎来自UserNotificationCenter
进程,它并没有以某种方式报告自己是最前端的应用程序,尽管它确实有键盘焦点。
"UserNotificationCenter"one_answers"UserNotificationCenter"是后台应用程序(info.plist中的NSUIElement
键为1)。
proc.frontmost()
在后台进程中始终为false(无菜单且不在Dock中)。
NSWorkspace.sharedWorkspace().frontmostApplication()
不适用于后台应用程序。
要获得活动应用程序,请使用NSWorkspace
类中的activeApplication
方法
这是AppleScript:
set pyScript to "from AppKit import NSWorkspace
activeApp = NSWorkspace.sharedWorkspace().activeApplication()
print activeApp['NSApplicationName'].encode('utf-8')
print activeApp['NSApplicationProcessIdentifier']"
set r to do shell script "/usr/bin/python -c " & quoted form of pyScript
set {localizedAppName, procID} to paragraphs of r -- procID is the unix id
使用不推荐使用的方法更新:
set pyScript to "from AppKit import NSWorkspace
for app in NSWorkspace.sharedWorkspace().runningApplications():
if app.isActive():
print app.localizedName().encode('utf-8')
print app.processIdentifier()
break"
set r to do shell script "/usr/bin/python -c " & quoted form of pyScript
set {localizedAppName, procID} to paragraphs of r -- procID is the unix id
要从进程ID获取前窗口,请使用procID
变量,如下所示:
tell application "System Events"
tell (first process whose unix id = procID)
log (get properties) -- properties of this process
tell window 1 to if exists then log (get properties) -- properties of the front window of this process
end tell
end tell