使用告诉应用程序块时,Automator 服务脚本无法检测到打开的应用程序

Automator service script fails at detecting open app when tell application block is used

我写了一个小服务脚本来在 Finder 的任意文件夹上打开 iTerm 终端window。

我想让它检查 iTerm 是否 运行ning,以及它是否要在新选项卡而不是现有选项卡中打开终端会话。

脚本是这样的:

on run {input, parameters}

set cdPath to "cd " & (quoted form of POSIX path of (input as string))

if application "iTerm" is running then
    display notification "running"
    tell application "iTerm"
        set termWin to (current terminal)
        tell termWin
            launch session "Default"
            tell the last session
                write text cdPath
            end tell
        end tell
    end tell
else
    display notification "not running"
    tell application "iTerm"
        activate
        set termWin2 to (current terminal)
        tell termWin2
            tell the last session
                write text cdPath
            end tell
        end tell
    end tell
end if
return input
end run

问题是,当我 运行 脚本作为服务时,它总是表现得好像 iTerm 已经 运行ning(显示 "running" 通知),即使 iTerm已关闭,很明显不是 运行ning.

但是如果我将相同的脚本粘贴到脚本编辑器(将 cdPath 设置为文字,如 set cdPath to "cd /etc")并直接执行它,它将正常工作,打开一个新的 iTerm 实例或重新使用现有的并创建一个新标签,并显示相应的通知。

如果我将脚本简化为只显示通知(像这样删除 tell aplication 块:

on run {input, parameters}

set cdPath to "cd " & (quoted form of POSIX path of (input as string))

  if application "iTerm" is running then
    display notification "running and path is " & cd
  else
    display notification "not running and path is " & cdPath
  end if
  return input
end run

它将按预期运行(相应地显示 'running' 或 'not running')。

但是如果我添加 "tell application" 部分,它将始终通过 "running" 分支,无论如何。

例如:

on run {input, parameters}
set cdPath to "cd " & (quoted form of POSIX path of (input as string))

  if application "iTerm" is running then
    display notification "running"
  else
    display notification "not running"
    tell application "iTerm"
        activate
    end tell
  end if
  return input
end run

将始终打开 iTerm(即使 tell application "iTerm" 它在 "not running" 分支上,但显示 "running" 通知,来自 "is running" 分支...仅存在 "tell application" 将触发打开应用程序,然后服务为 运行。

有什么办法可以避免这种情况吗?为什么 "tell application" 阻止打开应用程序,即使它在条件的另一个分支上?

"is running" 的使用导致了 tell 块的 运行。使用系统事件获取 运行ning 进程的名称以检查应用程序是否为 运行ning。这是重写的最终脚本示例,可以按您的意愿运行。

on run {input, parameters}

    set cdPath to "cd " & (quoted form of POSIX path of (input as string))

    tell application "System Events" to set theProcesses to name of every process whose visible is true

    if theProcesses contains "iTerm" then
        display notification "running"
    else
        display notification "not running"
        tell application "iTerm"
            activate
        end tell
    end if
    return input
end run

如果你仍然无法让它工作(在我的机器 运行ning OS X 10.11.1 上确实如此,那么你还可以添加包装任何 tell 块的技巧在 运行 脚本中,因此直到 运行 时间它才会编译。这是您的原始脚本,演示了这一点:

on run {input, parameters}

    set cdPath to "cd " & (quoted form of POSIX path of (input as string))

    tell application "System Events" to set theProcesses to name of every process

    if theProcesses contains "iTerm" then
        display notification "running"

        run script "tell application \"iTerm\"
        set termWin to (current terminal)
        tell termWin
            launch session \"Default\"
            tell the last session
                write text cdPath
            end tell
        end tell
    end tell"
    else
        display notification "not running"
        run script "tell application \"iTerm\"
        activate
        set termWin2 to (current terminal)
        tell termWin2
            tell the last session
                write text cdPath
            end tell
        end tell
    end tell"
    end if
    return input
end run

我想我找到了解释:

  • 任何 "is running" 短语需要在其前面有一个简短的 "delay" 才能可靠地 return 一个正确的答案......但是 仍然 如果作为应用程序的服务调用则不会这样做 - ?因为 ? :
  • 此外,我猜想 Automator 脚本在 运行 作为服务之前以某种方式 "pre-processed"。
    所有 if 分支都被评估(播放)并因此被激活 "just in case"。
    在 jweaks 代码中,iTerm 仅在第 2 个子句中直接受到影响 ("tell ...")。

在 ScriptEditor、Automator 和 Safari 中作为服务尝试此代码:

display notification "" & running of application "TextEdit"
tell application "TextEdit" to activate
quit application "TextEdit"
display notification "" & running of application "TextEdit"

您将在 AppleScript/Automator (=> false + true) 和 Safari (true + true) 中得到不同的结果。
特别是第二次通知中 AppleScript/Automator 的 true 非常有说服力。

... 但是,如果您在 "quit" 行之后插入一分钟延迟,比如说 0.01,运行ning 将被测试为 "false" - 如果脚本是运行 来自 AppleScript/Automator.