El script de servicio de Automator SIEMPRE inicia la aplicación, sin tener en cuenta las condiciones

Escribí un pequeño script de servicio para abrir una ventana de terminal iTerm en una carpeta arbitraria en Finder.

Quiero que verifique si iTerm se está ejecutando y si es para abrir la sesión de terminal en una nueva pestaña en lugar de en una existente.

El guión es así:

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

El problema es que cuando ejecuto el script como un servicio, siempre se comportará como si iTerm ya se estuviera ejecutando (mostrando la notificación "en ejecución"), incluso si iTerm está cerrado y claramente NO se está ejecutando.

Pero si pego la misma secuencia de comandos en el Editor de secuencias de comandos (configurando cdPath en un literal, como set cdPath to "cd /etc") y la ejecuto directamente, funcionará correctamente, ya sea abriendo una nueva instancia de iTerm o reutilizando una existente y creando una nueva pestaña, y mostrar la correspondiente notificaciones

¿Que está pasando aqui? ¿Por qué ejecutar el script como un servicio detectaría que la aplicación se está ejecutando sin importar qué?

Actualizar

Si simplifico el script para que solo muestre las notificaciones de esta manera:

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"
  end if
  return input
end run

Se comportará como se espera (mostrando 'en ejecución' o 'no en ejecución' según corresponda).

Pero si agrego la parte "decir a la aplicación", siempre irá a través de la rama "en ejecución", pase lo que pase.

P.ej:

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

Siempre abrirá iTerm (incluso si tell application "iTerm"está en la rama "no en ejecución", pero mostrará la notificación "en ejecución", desde la rama "en ejecución"... La mera presencia de una "aplicación de aviso" activará la apertura de la aplicación y luego se ejecuta el Servicio.

¿Hay alguna manera de eludir esto?

Gracias y saludos.

También encontré este problema y lo encontré muy molesto. ¿Ha encontrado alguna solución recientemente? Gracias.

Respuestas (3)

Las restricciones de seguridad de El-Capitans NO son responsables del comportamiento erróneo anterior. Probé el script un poco más y descubrí que:

  • Cualquier frase "se está ejecutando" debe tener un breve "retraso" delante de ella para devolver de manera confiable una respuesta verdadera... pero aún así no lo hará si se llama como un servicio de aplicación.
  • Además, supongo que los scripts de Automator son de alguna manera "preprocesados" antes de ejecutarse como Servicios.
    Todas las ramas if se evalúan (se reproducen) y, por lo tanto, se activan "por si acaso".

En el código jweaks en el desbordamiento de la pila , iTerm solo se ve afectado directamente en la segunda cláusula ("decir...").

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

if theProcesses contains "iTerm" then display notification "running"
else [...]


Pruebe este código en ScriptEditor, Automator y como servicio en Safari:

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

Obtendrá diferentes resultados de AppleScript/Automator (=> false + true ) y Safari ( true + true ). Especialmente la verdad
de AppleScript/Automator desde la segunda notificación es bastante reveladora. ... sin embargo, si inserta solo un minuto de retraso, digamos 0.01, después de la línea "salir", la ejecución se probará como "falsa", si el script se ejecuta desde AppleScript/Automator.

A veces también he notado ese comportamiento al ejecutar el script, es extraño. Aunque la mayoría de las veces no sucede cuando no se ejecuta el script a través del Editor de scripts. Sin embargo, aquí hay una mejor alternativa:

tell application "System Events"
    # Adding tell application block has no effect on the if condition
    # Try it with TextEdit, that's what I using to try this code, and works fine.
    if (the name of application processes as text) contains "iTerm" then
        # Will quit the application if running
        log "Running"
        tell application "iTerm" to quit
    else
        # Will launch the application otherwise.
        log "Not Running"
        tell application "iTerm" to activate
    end if
end tell
¿Solucionaría eso mi problema? Puedo "registrar" la aplicación ejecutándose tal como está. Pero necesito interactuar con la aplicación (como abrir una nueva pestaña o no). Como tal, necesitaría un bloque "dile a la aplicación iTerm", ¿verdad? ¿Cómo podría abordar mi problema con su alternativa?
El registro es solo para demostración, use su código como desee.
Entiendo que. De ahí mi bloque donde uso 'mostrar notificación'. Y como dije, mientras no use el código de "aplicación indicadora" funciona como se esperaba, pero cuando use un bloque de aplicación indicadora en cualquiera de las ramas, siempre mostrará "en ejecución". En su ejemplo, intente reemplazar 'registro "no en ejecución"' con un bloque "iTerm" de la aplicación, y verá que siempre registrará "en ejecución" y nunca "no en ejecución" (nuevamente, ejecutando el bloque como un servicio). Creo que es posible que no haya leído mi pregunta por completo. Gracias de cualquier manera.
Su código es funcionalmente equivalente a mi segundo ejemplo de código, no agrega nada nuevo sino otra forma de expresar lo mismo. Como tal, esta no es una respuesta, pero solo está reformulando mi pregunta ...: P Muchas gracias de todos modos, pero elimine esta respuesta si no tiene nada más que agregar. Saludos.
¿Algo más que añadir? Si no, ¿podría eliminar su respuesta? Desvía la atención de las preguntas, ya que parece como si ya estuviera respondida... Gracias de nuevo.
Umm no. Si la aplicación se está ejecutando, registrará "No se está ejecutando" e iniciará la aplicación ya que le indica que se active, si se está ejecutando, no sucederá nada más que solo iniciar sesión. Obviamente, si lo ejecuta varias veces, solo la primera vez estará en la condición "No se está ejecutando" y el resto estará "En ejecución" hasta que lo abandone. Puede decirle a la aplicación que se cierre en el bloque en ejecución y verá que la condición se mantiene como se esperaba.
¿Lo has probado como un flujo de trabajo de servicio? tengo, y me produce "corriendo", abre la aplicacion, y luego la cierra...
Míralo aquí en todo su esplendor: vid.me/0fTZ :)
La mera existencia del bloque "decir" hace que la aplicación se abra cuando se ejecuta el servicio...
Una vez más, esto no responde a mi pregunta. Por favor, elimine esta respuesta tal como está. Gracias y saludos.

Acabo de encontrar una manera de hacerlo. Aunque estoy creando una aplicación en lugar de un servicio, son casi lo mismo. La idea básica es poner tell application iTermen otro script o entre comillas, de modo que el proceso de optimización no haga que se abra iTerm antes de ejecutar este script. Así obtendrás el resultado real de if application "iTerm" is running.

Pero en el script citado, dado que hay tell applicationuna parte, ya sabemos que iTerm se abrirá antes que nada, podemos activateiTerm directamente y usar el current session of current terminal(de hecho, incluso en Automator, esto todavía funciona incluso si iTerm no se abre primero). No estoy seguro si delay 0.01es necesario aquí (puede probar en su computadora). Pero este funciona para mi propósito, que es abrir la ruta actual del Finder en una nueva ventana de iTerm en el escritorio actual. Y si iTerm no se está ejecutando, no abrirá dos ventanas de iTerm.

Déjame saber lo que piensas. :-)

on run {input, parameters}
    tell application "Finder"
        set dir_path to quoted form of (POSIX path of (folder of the front window as alias))
    end tell
    CD_to(dir_path)
end run

on CD_to(theDir)
    if application "iTerm" is running then
        #display dialog "Running" # for debug
        run script "
            on run {q}
                tell application \":Applications:iTerm.app\"
                    set term to (make new terminal) # make a new window in current desktop since I don't want to mess with current ones
                    tell term
                        launch session \"Default\"
                        set sesh to current session
                    end tell
                    tell sesh
                        write text \"cd \" & q & \";clear;\"
                    end tell
                    activate
                end tell
            end run
        " with parameters {theDir}
    else
        #display dialog "Not Running" # for debug
        run script "
            on run {q}
                tell application \":Applications:iTerm.app\"
                    delay 0.01
                    activate
                    set sesh to current session of current terminal
                    tell sesh
                        write text \"cd \" & q & \";clear;\"
                    end tell
                end tell
            end run
        " with parameters {theDir}
    end if
end CD_to
# part of code comes from http://peterdowns.com/posts/open-iterm-finder-service.html