如何在AppleScript中检查,如果一个应用程序正在运行,而不启动它 – 通过osascript实用程序
考虑下面的AppleScript:
on is_running(appName) tell application "System Events" to (name of processes) contains appName end is_running set safRunning to is_running("Safari") if safRunning then tell application "Safari" -- Stuff I only want executed if Safari is running goes here. end tell return "Running" else return "Not running" end if
问题是:当我通过osascript
命令行实用程序运行它时,如果Safari没有运行,它会启动并且脚本报告“正在运行”。 这不是我期望或期望的行为。 请注意,它在AppleScript编辑器中运行时按预期方式工作。
这是一个osascript
错误/已知的问题? 或者是因为我失踪的原因而出于某种目的? 任何人都可以得到它按要求工作? (顺便说一句,我正在运行OSX 10.7.5;我不明白如何让osascript
报告一个版本号)。
如果注释掉tell
/ end tell
行,它的行为就像我所预期的那样:如果Safari没有运行,它不会启动它,并打印出“Not running”。 所以在我看来 ,这个tell
是什么导致Safari被启动,但它不需要实际执行,只是在脚本中出现…? 有一段时间,我想知道如果也许这只是tell
应该如何工作,但因为它不在 AppleScript编辑器中这样的工作,我猜不是…
事实上,这里有另外一个类似的行为:
on is_running(appName) tell application "System Events" to (name of processes) contains appName end is_running set safRunning to is_running("Safari") return safRunning if false then tell application "Safari" end tell end if
这仍然会启动Safari,尽pipe在返回语句之后, if false
块之内的if false
! (但是,在AppleScript编辑器中,这还是可以的。)
顺便说一句,这种行为不仅限于Safari,但它也不是通用的:
- 受影响的应用程序包括:Safari,TextEdit,iPhoto,AppleScript编辑器,iTerm,…
- 不受影响的应用程序包括:Google Chrome,iTunes,预览,邮件,terminal,地址簿,Echofon,…
那么,有没有人有任何想法可以解决这个问题? 这是一个osascript
错误吗? 还是我错过了AppleScript的语义?
对于上下文:我试图编写一个脚本(从一些pythonembedded/调用),查询打开的浏览器的任何标签,他们已经打开的URL; 我已经得到它一切正常工作, 除了它总是启动Safari,无论是否打开。 我把上面简单的testing案例的不良行为归结为一个例子。 我不知道有什么办法从python运行这个脚本,而不使用osascript
,除了appscript ,我不想使用,因为它不再被开发/支持/推荐 。
非常感谢所有的投入/见解!
我怀疑你得到这个的原因是因为每次你使用osascript从命令行调用脚本时,脚本正在被编译。
在告诉应用程序上编译的行为将使应用程序启动。
使用osascript从命令行调用脚本从一个预编译的文件,即。 scpt不会导致这种行为,因为没有编译完成。
但是从纯文本(.txt,.sh)文件调用它将启动应用程序。
如果你不想使用一个.scpt文件,并想使用纯文本文件,那么你可以尝试把运行脚本命令放在applescript中。
on is_running(appName) tell application "System Events" to (name of processes) contains appName end is_running set safRunning to is_running("Safari") if safRunning then run script "tell application \"Safari\" open location \"http://google.com\" end tell" return "Running" else return "Not running" end if
运行脚本中的脚本只在需要时编译。 你将需要像在我的例子中的引号那样转义任何字符。
如果您先将脚本写在一个普通的applescript文档中,然后编译它来检查错误,那将会更容易一些。
然后将其复制到纯文本文件。
更新 **
我在上面使用的方法是从我以前用来解决这个问题的一个老脚本开始的。
答案是有效的,并不是要优雅。 😉
我其实喜欢下面的user1804762方法。 虽然它的工作,但觉得答案不够清楚,所以我会举一个例子来使用它。
set appName to "Safari" if application appName is running then tell application id (id of application appName) open location "http://google.com" end tell return "Running" else return "Not running" end if
这个脚本可以使用osascript从命令行运行
例:
osascript /Users/USERNAME/Desktop/foo.scpt
注意脚本被保存为编译脚本。 这将工作正常,你也可以保存和使用它作为纯文本脚本。
即
osascript /Users/USERNAME/Desktop/foo.applescript
一些信息:
“增强的应用程序对象模型”:
tell application "iTunes" if it is running then pause end if end tell
你也可以这样做:
if application "iTunes" is running then tell application "iTunes" to quit end if
你也可以这样做:
get name of application "iTunes" get version of application "iTunes"
并完成旅程:
get id of application "TextEdit" --> "com.apple.TextEdit" tell application id "com.apple.TextEdit" make new document end tell
那就是“增强的应用程序对象模型”。 如果应用程序仍然启动(例如,第一次编译和执行脚本),我认为这是因为AS必须从应用程序中得到一些它没有在字典中find的信息(或类似的东西…? )。
好吧,我知道这个问题真的很老,但是我偶然发现了一个不同的问题,不得不考虑这些答案中有多复杂。
简单的代码来实现你想要的(ed)是:
tell application "System Events" if application process "Safari" exists then -- do stuff you want to do only if Safari exists end if end tell
在较旧的系统上,语法曾经是:
tell application "System Events" if exists of application process "Safari" is true then -- do stuff you want to do only if Safari exists end if end tell
其中一个应该肯定为你工作,只有当一个应用程序正在运行的Applescript的行动解决scheme的勇敢的search者。
哦! 奖金提示:如果您不确定应用程序进程名称是什么( 通常但不一定是应用程序名称),则在编写最终脚本运行之前…
tell application "System Events" get every application process end tell
并在结果中find您的应用程序进程名称。
这是一个运行该命令的屏幕截图。 (请注意Google Chrome Helper实例的数量,感谢Google!)
HTH!
tell application "Finder" set applicationsnames to get the name of every process whose visible is true end tell set appName to "Safari" if applicationsnames does not contain appName then say (appName & " is not running") --add here what you want to happen end if return applicationsnames
这是返回{"Finder", "JavaAppLauncher", "firefox", "Microsoft Word", "iTunes", "AppleScript Editor"}
希望这可以帮助
所有以前提出的答案都遭受同样的问题,但是:
他们通过名字寻找应用程序。 但是,用户可能会重命名该应用程序,然后脚本会认为该应用程序不会运行,实际上它确实会运行。
要正确检查正在运行的应用程序,应该通过其用户无法更改的包ID来find它。
捆绑ID可以用这个命令查询,例如:
tell application "System Events" get bundle identifier of application process "Safari" end tell
要检查具有特定包ID的应用程序是否正在运行,请使用以下代码:
tell application "System Events" set ids to bundle identifier of every application process if ids contains "com.apple.safari" then return "Running" else return "Not running" end if end tell
此外,下面是一个示例,用于检查应用程序是否正在运行,然后退出,然后重新启动,确保以前运行的应用程序重新启动,而不是其他可能存在的其他副本:
set bundleID to "com.apple.safari" set apps to runningApps(bundleID) set appCount to length of apps if appCount is not 0 then quit application id bundleID repeat while length of runningApps(bundleID) = appCount -- wait for the app to quit end repeat open first item of apps end if on runningApps(bundleID) -- The try block is to catch the rare case of having more than one -- copy of an app running at the same time. Unfortunately, in that -- case this code will not run as expected, because we don't get the -- correct list of multiple items back then. But at least the script -- will not crash from it but handle it gracefully. tell application "System Events" try return application file of (every application process whose bundle identifier = bundleID) end try end tell return {} end runningApps