El comando «delay» de AppleScript no funciona desde que se cambió a Yosemite

Nota: El problema con delay se solucionó en OS X 10.11 El Capitan.

Desde que actualicé a Yosemite, Applescripts que usan retrasos han dejado de funcionar . ¿Cómo puedo solucionar esto?

Aquí está el Applescript más simple del mundo, en aras de un ejemplo sencillo:

set volume output volume 0 delay 5 set volume output volume 20 delay 5 set volume output volume 0 delay 5 set volume output volume 20 delay 5 set volume output volume 0 delay 5 set volume output volume 20 delay 5 set volume output volume 0 

Eso debería tardar 30 segundos en completarse. Si lo ejecuto en Script Editor (anteriormente Applescript Editor), tarda 30 segundos en completarse. Pero si guardo este script como una aplicación, cuando lanzo la aplicación, los retrasos se ignoran y la aplicación tarda una fracción de segundo en completarse.

¿Cómo puedo obligar a Applescript a retrasar una cantidad específica? de tiempo antes de pasar al siguiente paso? ¿Es esto un problema técnico de Yosemite? ¿Existe una solución alternativa confiable?

Comentarios

  • Esto funciona como se esperaba en mi Mac (10.10.1)
  • Alguna idea ¿Qué causa que no funcione en el mío? Para aclarar: funciona en Script Editor, pero si guardo el script como una aplicación y luego ejecuto la aplicación, los retrasos se ignoran. Es ‘ la cosa más extraña.
  • Tengo el mismo problema en 10.10.3
  • Reportado a Apple: openradar.me/21588747
  • Este problema se solucionó en OS X 10.11 El Capitan.

Respuesta

Nota: El problema con delay se corrigió en OS X 10.11 El Capitan.

@ 2oh1, tienes la idea básica correcta en tu respuesta, pero aquí tienes una respuesta completa y correcta:

La única forma razonable de evitar esto es invocar «retraso» dentro de un bucle que garantice que transcurre la duración deseada antes de continuar. La mejor manera de hacerlo es anular «retraso» con un controlador personalizado:

on delay duration set endTime to (current date) + duration repeat while (current date) is less than endTime tell AppleScript to delay endTime - (current date) end repeat end delay 

Esto le permite dejar el resto de su script sin cambios y puede usar «delay» normalmente, por ejemplo,

delay 5 display alert "I like cake!" 

[NOTA: Normalmente, el controlador personalizado usaría «continuar la duración del retraso» para invocar el «retraso» incorporado, pero descubrí que, aunque esto funciona dentro del Editor de secuencias de comandos, devuelve un error cuando se usa dentro de un subprograma («No se puede continuar el retraso. (-1708) ”). Resolví ese problema diciéndole directamente a AppleScript que manejara el comando de retraso en lugar de usar «continuar» para llegar allí.]

El problema es que delay procesa al usuario entrada mientras pausa la secuencia de comandos, por lo que aún puede hacer clic en los menús o ventanas mostradas por un subprograma, y hay un error (corregido en 10.11) donde la entrada del usuario hace que delay no espere el duración completa antes de reanudar la ejecución del script. Si no interactúa con el subprograma, delay funciona correctamente.

Comentarios

  • ¿Es todo de esto es un error, o hay una razón por la que el retraso funciona de esta manera con Yosemite?
  • Es un error que el retraso no es ‘ t retrasar.
  • Es ‘ tan extraño. Estaba jugando con un código de manzana que usa delay la otra noche, y de repente, delay estaba funcionando correctamente de nuevo. Supuse que el error se había solucionado . Una hora más tarde, aunque nada había cambiado, el error había vuelto. Estoy ‘ realmente desconcertado. No ‘ importa . Estoy ‘ usando una variable para establecer el tiempo y el retraso hasta cinco minutos más tarde (por ejemplo), y ‘ funciona perfectamente . Entonces … problema resuelto, pero eso no ‘ no explica por qué existe el problema. Interesante, interesante, interesante.
  • Porque Apple se equivocó. Apple El software es mucho menos confiable desde que comenzaron a lanzar OS X anualmente. Echo de menos las versiones menores de OS X superiores (como 10.6.8) donde el sistema operativo era sólido como una roca. Simplemente no ‘ ya no obtienes ese tipo de experiencia.
  • Si es ‘ un error (que estoy de acuerdo with), me pregunto por qué no ‘ t esto todavía no está arreglado. ¿Alguien aquí ha hecho un informe de radar? Entonces, ¿podría publicar su identificación? (o / también publicar en openradar.me)

Responder

Mientras luchaba contra este mismo problema, encontré esta respuesta a una pregunta no tan relacionada y decidí probarla y parece que funciona para mí.

Reemplace delay 5 con do shell script "/bin/sleep 5" y obtenga el mismo resultado.

Comentarios

  • ¡Gracias por compartir! Como dije anteriormente, ‘ no puedo probar esto porque, por razones que no tienen sentido para mí, el retraso 5 está funcionando como debería para mí en este momento (acabo de probar de nuevo hace un momento). No tengo idea de por qué esto a veces funciona y a veces falla.Es ‘ tan extraño. Terminé usando una solución en la que obtengo la hora actual y la configuro como una variable, y luego pause el script hasta que la hora sea variable más un minuto (con un retraso de 1 minuto, obviamente). Es ‘ torpe, pero ‘ funcionó sin problemas durante meses, mientras que una simple demora ha sido intermitente. Ugh.
  • Estoy ejecutando 10.10.5 y esta solución no funciona y también bloquea el script durante la suspensión
  • @Greg: Si «bloquea el script» para la duración del sueño, entonces ‘ está funcionando. /bin/sleep espera la duración del sueño y no regresa hasta que se completa. Por el contrario, el comando delay incorporado de AppleScript ‘ maneja los eventos de entrada del usuario mientras el script está en pausa. (Que es donde radica el error: si hay una entrada de teclado del usuario, delay continúa la ejecución del script antes de que se complete la duración del retraso).

Respuesta

No estoy diciendo que esta sea la mejor solución, pero parece haber resuelto mi problema. En lugar de usar un simple retraso, que se está ignorando por razones que no entiendo, he cambiado a obtener la hora y recorrer un bucle hasta que se alcanza una nueva hora (todavía usa un retraso, pero no importa si ignora el retraso ya que el script no continúa hasta que se alcanza el tiempo).

# Pause for five minutes set GetTheTime to current date set NewTime to GetTheTime + (5 * minutes) repeat while (current date) is less than NewTime delay 60 end repeat 

Todavía me muero por saber por qué se ignora la demora (¿o se acelera drásticamente?! ??), pero esto se el trabajo está hecho, por torpe que sea.

Comentarios

  • El » retraso » comando no ‘ t está » acelerado » , es ‘ s siendo interrumpido. Mientras se demora, se sienta en un bucle que verifica si hay eventos de entrada de teclado para poder verificar el período de comando. Aparentemente, está saliendo incorrectamente del bucle de retardo cuando se detecta cualquier entrada del usuario.
  • ¡Interesante! ‘ descubro que ‘ se ignora (¿se acelera? ¿Se interrumpe?) Incluso cuando mi Mac está inactiva, pero no ‘ No sé por qué.
  • Una vez que un evento de entrada de usuario está en la cola de eventos, delay continuará ser interrumpido hasta que algo maneje los eventos y los elimine de la cola.

Responder

Encontré un trabajo- en una publicación del foro en alemán. Agregue estas líneas al principio de su secuencia de comandos:

use framework "Foundation" use scripting additions current application"s NSThread"s sleepForTimeInterval:1 

Comentarios

  • I ‘ Tengo problemas para probar su respuesta porque, por cualquier motivo, el retraso funciona como se esperaba en mi Mac. No tengo ni idea de porqué. ‘ estoy ejecutando 10.10.3. ¿Quizás Apple solucionó este error? O tal vez ‘ es solo un problema intermitente que no ‘ afecta a mi Mac en este momento. Puaj. Sin embargo, como dije anteriormente, mi solución es que Applescript obtenga la hora actual y luego se retrase hasta la hora actual más x.
  • También estoy ejecutando 10.10.3 y todavía veo el problema. Dado que no todo el mundo ve el problema, es ‘ probablemente intermitente o relacionado con software de terceros o con determinadas preferencias. Quién sabe. Por cierto, su solución alternativa tiene probablemente la desventaja de que la aplicación sigue usando el 100% del tiempo de CPU mientras espera, mientras que el comportamiento de retraso adecuado es poner la aplicación en suspensión durante ese tiempo, por lo que usa menos energía.
  • Estoy ejecutando 10.10.5 y esta solución no funciona.
  • @ThomasTempelmann: El problema ocurre cuando hay una entrada del usuario. Si no ‘ t hace clic o escribe mientras se ejecuta la secuencia de comandos, el error no ‘ t se activa.
  • Tenga en cuenta que esta solución hace que la aplicación se congele durante la suspensión. delay procesa la entrada del usuario mientras el script está en pausa, por lo que aún puede interactuar con menús y ventanas, por ejemplo.

Respuesta

carzyj tenía lo que considero la mejor respuesta, pero cuando se combina con el método de Chris Page, se obtiene:

on delay duration do shell script "/bin/sleep " & duration end delay 

Puede comentar desde «retraso» hasta «retraso final» para volver al retraso original.

Comentarios

  • I También hice una modificación de código similar, antes de ver esto. Estoy ejecutando 10.10.5 y esta solución no funciona y también bloquea el script durante la duración de la suspensión.

Respuesta

esta es una modificación de la solución @ chris-page

Parece haber un equilibrio entre la capacidad de respuesta y la captura precisa del retraso.

on delay duration set endTime to (current date) + duration repeat while (current date) is less than endTime set delta to duration / 100 if duration < 0.2 then set delta to 0.2 end if tell AppleScript to delay delta end repeat end delay 

Pero en lugar de decirle a Applescript que se retrase durante la duración total, simplemente le decimos que se retrase durante una fracción de la duración. si el período es menor de lo que permite Apple (1/60 de segundo), entonces configurémoslo en ese delta. Para que podamos mantener cierta capacidad de respuesta, pero aún así ser precisos. La sospecha es que a veces el retraso no funciona para que el ciclo repeat while mantenga el hilo bloqueado, pero en escenarios exitosos, queremos que el retardo delta sea corto para que el proceso aún pueda interrumpirse

Comentarios

  • Acortar el retraso solicitado es innecesario y solo puede hacer que el script se ejecute más lento y consuma más CPU mientras espera. Mi versión simplemente llama al retraso hasta que haya transcurrido la duración deseada, lo que permite que delay demore todo lo que pueda antes de que continúe la ejecución.
  • Tenga en cuenta que desde esta respuesta se publicó, actualicé mi código para usar delay endTime - (current date) en lugar de delay duration, lo que garantiza que si delay no ‘ t se interrumpe, no ‘ t pausar el script por más tiempo del tiempo solicitado originalmente , que puede haber sido lo que estaba tratando de abordar con esta respuesta.

Respuesta

Entonces, para poner todo junto, creo que Chris quiere decir esto:

on delay duration set endTime to (current date) + duration repeat while (current date) is less than endTime tell AppleScript to delay endTime - (current date) end repeat end delay 

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *