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 ‘ internodelay
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 dedelay duration
, o que garante que sedelay
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