O comando “delay” do AppleScript não funciona desde a mudança para Yosemite

Nota: O problema com delay foi corrigido no OS X 10.11 El Capitan.

Desde que atualizei para o Yosemite, os Applescripts que usam atrasos pararam de funcionar . Como posso corrigir isso?

Aqui está o Applescript mais simples do mundo, por causa de um exemplo fácil:

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 

Isso deve levar 30 segundos para ser concluído. Se eu executá-lo no Editor de scripts (antigo Editor de Applescript), ele leva 30 segundos para ser concluído. Mas se eu salvar este script como um aplicativo, quando eu inicio o aplicativo, os atrasos são ignorados e o aplicativo leva uma fração de segundo para ser concluído.

Como posso forçar o Applescript a atrasar um determinado valor de tempo antes de passar para a próxima etapa? É uma falha do Yosemite? Existe uma solução alternativa confiável?

Comentários

  • Isso funciona como esperado no meu Mac (10.10.1)
  • Qualquer ideia o que faz com que ele não funcione no meu? Para esclarecer: funciona no Editor de Script, mas se eu salvar o script como um aplicativo e depois iniciar o aplicativo, os atrasos são ignorados. É ‘ é a coisa mais estranha.
  • Tenho o mesmo problema em 10.10.3
  • Reportado à Apple: openradar.me/21588747
  • Esse problema foi corrigido no OS X 10.11 El Capitan.

Resposta

Observação: O problema com delay foi corrigido no OS X 10.11 El Capitan.

@ 2oh1, você tem a ideia básica certa em sua resposta, mas aqui está uma resposta completa e correta:

A única maneira razoável de contornar isso é invocar “delay” dentro de um loop que garanta que a duração desejada passe antes de continuar. A melhor maneira de fazer isso é substituir “delay” por um manipulador 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 

Isso permite que você deixe o resto do seu script inalterado e você pode usar “delay” normalmente, por exemplo,

delay 5 display alert "I like cake!" 

[NOTA: Normalmente, o manipulador personalizado usaria “continuar a duração do atraso” para invocar o “atraso” integrado, mas descobri que, embora funcione no Editor de scripts, ele retorna um erro quando usado em um miniaplicativo (“Não é possível continuar o atraso. (-1708) ”). Eu contornei esse problema dizendo diretamente ao AppleScript para lidar com o comando de atraso em vez de usar “continue” para chegar lá.]

O problema é que delay processa o usuário entrada ao pausar o script, então você ainda pode clicar em menus ou janelas exibidos por um miniaplicativo, e há um bug (corrigido em 10.11) onde a entrada do usuário faz com que delay não espere o duração total antes de retomar a execução do script. Se você não interagir com o miniaplicativo, delay funcionará corretamente.

Comentários

  • É tudo disso é um bug, ou há um motivo pelo qual o atraso está funcionando dessa forma com o Yosemite?
  • É um bug que o atraso não ‘ t atrasando.
  • É ‘ tão estranho. Eu estava mexendo em um script de maçã que usa delay na outra noite e, de repente, o delay estava funcionando corretamente novamente. Presumi que o bug tinha sido corrigido . Uma hora depois, embora nada tivesse mudado, o bug estava de volta. Eu ‘ estou realmente perplexo. Não ‘ não importa, no entanto . Eu ‘ estou usando uma variável para definir o tempo e atrasar até cinco minutos depois (por exemplo), e ‘ está funcionando perfeitamente . Então … problema resolvido, mas isso não ‘ não explica por que o problema existe. Interessante, interessante, interessante.
  • Porque a Apple fez uma besteira. Apple o software é muito menos confiável desde que eles começaram a lançar o OS X anualmente. Sinto falta das versões menores do OS X superiores (como 10.6.8), onde o sistema operacional era sólido como uma rocha. Você simplesmente não ‘ deixa de ter esse tipo de experiência.
  • Se ‘ for um bug (o que eu concordo com), por que não ‘ isso ainda não foi corrigido, eu me pergunto. Alguém aqui fez um relatório de radar? Você poderia, então, postar seu ID? (ou / também poste em openradar.me)

Resposta

Enquanto lutava contra esse mesmo problema, me deparei com esta resposta a uma pergunta não tão relacionada e decidiu tentar e parece que trabalhe para mim.

Substitua delay 5 por do shell script "/bin/sleep 5" e obtenha o mesmo resultado.

Comentários

  • Obrigado por compartilhar! Como eu disse anteriormente, ‘ não consigo testar isso porque, por motivos que não fazem sentido para mim, o delay 5 está funcionando como deveria para mim agora (acabei de testar novamente há um momento). Não tenho ideia de por que isso às vezes funciona e às vezes falha.É ‘ tão estranho. Acabei usando uma solução alternativa onde obtenho a hora atual e a defino como uma variável e, em seguida, pauso o script até que a hora seja variável mais um minuto (para um atraso de 1 minuto, obviamente). Ele ‘ é desajeitado, mas ‘ funcionou perfeitamente por meses, enquanto um simples atraso foi intermitente. Ugh.
  • Estou executando o 10.10.5 e esta solução não funciona e também bloqueia o script durante o sono
  • @Greg: Se “bloquear o script” para a duração do sono, então ‘ está funcionando. /bin/sleep aguarda a duração do sono e não retorna até que seja concluído. Em contraste, o comando ‘ interno delay do AppleScript trata os eventos de entrada do usuário enquanto o script está pausado. (É aí que reside o bug: se houver entrada do teclado do usuário, delay continua a execução do script antes que a duração do atraso seja concluída.)

Resposta

Não estou dizendo que esta seja a melhor solução, mas parece ter resolvido meu problema. Em vez de usar um simples atraso, que está sendo ignorado por razões que não entendo, mudei para obter a hora e fazer um loop até que uma nova hora seja atingida (ainda usa um atraso, mas não importa se ignora o atraso, pois o script não continua até o tempo é atingido).

# 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 

Ainda estou morrendo de vontade de saber por que o atraso está sendo ignorado (ou dramaticamente acelerado?! ??), mas isso fica o trabalho realizado, por mais desajeitado que seja.

Comentários

  • O ” atraso ” command isn ‘ t sendo ” acelerado ” , é ‘ está sendo interrompido. Enquanto atrasa, ele fica em um loop verificando se há eventos de entrada do teclado para que possa verificar o Período de Comando. Aparentemente, ele está saindo incorretamente do loop de atraso quando qualquer entrada do usuário é detectada.
  • Interessante! Eu ‘ estou achando que ‘ está sendo ignorado (acelerado? Interrompido?) Mesmo quando meu Mac está ocioso, mas eu não ‘ não sei por quê.
  • Assim que um evento de entrada do usuário estiver na fila de eventos, delay continuará para ser interrompido até que algo manipule os eventos e os remova da fila.

Resposta

Eu encontrei um trabalho- em uma postagem no fórum em alemão. Adicione estas linhas ao início do seu script:

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

Comentários

  • I ‘ estou tendo problemas para testar sua resposta porque, por algum motivo, o atraso está funcionando como esperado em meu Mac. Eu não tenho ideia do porquê. Eu ‘ estou executando 10.10.3. Talvez a Apple tenha corrigido esse bug? Ou talvez seja ‘ apenas um problema intermitente que não ‘ está afetando meu Mac neste momento. ECA. Porém, como eu disse acima, minha solução alternativa é fazer com que o Applescript obtenha a hora atual e depois adie até a hora atual mais x.
  • Estou executando a 10.10.3 também e ainda vejo o problema. Como nem todo mundo vê o problema, ele ‘ provavelmente está intermitente ou relacionado a software de terceiros ou a certas configurações de preferência. Quem sabe. BTW, sua solução alternativa provavelmente tem a desvantagem de que o aplicativo continua usando 100% do tempo de CPU enquanto espera, enquanto o comportamento de atraso adequado é colocar o aplicativo em hibernação durante esse período, usando menos energia.
  • Estou executando o 10.10.5 e esta solução não funciona.
  • @ThomasTempelmann: O problema ocorre quando há entrada do usuário. Se você não ‘ clicar ou digitar enquanto o script está em execução, o bug não será ‘ acionado.
  • Observe que essa solução faz com que o aplicativo congele durante o sono. delay processa a entrada do usuário enquanto o script está pausado, para que você ainda possa interagir com menus e janelas, por exemplo.

Resposta

carzyj teve o que considero a melhor resposta, mas quando combinado com o método de Chris Page, você obtém:

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

Você pode comentar “no atraso” até “atraso final” para reverter para o atraso original.

Comentários

  • I também fiz uma modificação de código semelhante, antes de ver isso. Estou executando 10.10.5 e esta solução não funciona e também bloqueia o script durante o sono.

Resposta

esta é uma modificação da solução @ chris-page

Parece haver um equilíbrio entre a capacidade de resposta e a captura precisa do atraso.

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 

Mas em vez de dizer ao Applescript para atrasar por toda a duração, apenas pedimos para atrasar por um período fracionário da duração. se o período for menor do que o permitido pela apple (1/60 de segundo), então vamos apenas defini-lo para esse delta. Para que possamos manter alguma capacidade de resposta, mas ainda assim sermos precisos. a suspeita é que às vezes o atraso não funciona de forma que o loop repeat while mantenha o thread travado, mas em cenários de sucesso, queremos que o delta de atraso seja curto para que o processo ainda possa ser interrompido

Comentários

  • Encurtar o atraso solicitado é desnecessário e só pode fazer o script rodar mais devagar e consumir mais CPU enquanto espera. Minha versão apenas chama o atraso até que toda a duração desejada tenha decorrido, permitindo que delay atrase o máximo que puder antes de continuar a execução.
  • Observe que, uma vez que esta resposta foi postado, atualizei meu código para usar delay endTime - (current date) em vez de delay duration, o que garante que se delay não ‘ for interrompido, não ‘ interromperá o script por mais tempo do que o tempo originalmente solicitado , que pode ser o que você estava tentando abordar com esta resposta.

Resposta

Então, para colocar tudo junto, acredito que Chris quis dizer isso:

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 

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *