El script del servicio de Automator SIEMPRE inicia la aplicación, sin tener en cuenta el condicional

3

Escribí una pequeña secuencia de comandos de servicio para abrir una ventana de terminal iTerm en una carpeta arbitraria en el Finder.

Quiero que compruebe 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 script 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 muy 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 lo ejecuto directamente, funcionará correctamente, ya sea abriendo una nueva instancia de iTerm o reutilizando una existente y creando una nueva y visualice las notificaciones correspondientes.

¿Qué está pasando aquí? ¿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 mostrar solo 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" en consecuencia).

Pero si agrego la parte "tell application", siempre pasará por la rama "running", pase lo que pase.

Por ejemplo:

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 se está ejecutando", pero muestra la notificación "en ejecución", desde la rama "se está ejecutando" ... La mera presencia de una "aplicación dice" activará la apertura de la aplicación y, a continuación, se ejecutará el Servicio.

¿Hay una manera de eludir esto?

Gracias y saludos.

    
pregunta yivi 15.11.2015 - 10:52

3 respuestas

1

Las restricciones de seguridad de El-Capitans NO son responsables por el comportamiento erróneo mencionado anteriormente. Probé el script un poco más y encontré que:

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

En jweaks código en pila desbordamiento , 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ás resultados diferentes de AppleScript / Automator (= > false + true ) y Safari ( true + true ). < br> Especialmente el verdadero de AppleScript / Automator de la segunda notificación es bastante revelador.

... sin embargo, si inserta un retraso de un minuto, 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.

    
respondido por el clemsam lang 07.12.2015 - 17:29
0

A veces también me he dado cuenta de que el comportamiento cuando se ejecuta 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 secuencias de comandos. 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
    
respondido por el user14492 15.11.2015 - 17:53
0

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 iTerm en otro script o en comillas, de modo que el proceso de optimización no lo haga abrir iTerm antes de ejecutar este script. Así obtendrás el resultado real de if application "iTerm" is running .

Pero en el script citado, ya que hay una parte tell application , ya sabemos que iTerm se abrirá antes que nada, podemos directamente activate iTerm y usar el current session of current terminal (de hecho, incluso en Automator, esto todavía funciona incluso si iTerm no se abre en primer lugar). No estoy seguro de si es necesario delay 0.01 aquí (puedes probar en tu 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
    
respondido por el astroboylrx 27.05.2016 - 00:21

Lea otras preguntas en las etiquetas