Il comando “delay” di AppleScript non funziona dal passaggio a Yosemite

Nota: Il problema con delay è stato risolto in OS X 10.11 El Capitan.

Da quando sono passato a Yosemite, gli Applescripts che utilizzano ritardi hanno smesso di funzionare . Come posso risolvere questo problema?

Ecco il più semplice Applescript del mondo, per fare un semplice esempio:

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 

Dovrebbero essere necessari 30 secondi per il completamento. Se lo eseguo in Script Editor (ex Applescript Editor) ci vogliono 30 secondi per completarlo. Ma se salvo questo script come app, quando avvio lapp, i ritardi vengono ignorati e lapp impiega una frazione di secondo per essere completata.

Come posso forzare Applescript a ritardare per un importo specificato di tempo prima di passare alla fase successiva? È un problema tecnico di Yosemite? Esiste una soluzione alternativa affidabile?

Commenti

  • Funziona come previsto sul mio Mac (10.10.1)
  • Qualche idea cosa fa sì che non funzioni sul mio? Per chiarire: funziona in Script Editor, ma se salvo lo script come app e poi avvio lapp, i ritardi vengono ignorati. ‘ è la cosa più strana.
  • Ho lo stesso problema il 10.10.3
  • Segnalato ad Apple: openradar.me/21588747
  • Questo problema è stato risolto in OS X 10.11 El Capitan.

Risposta

Nota: il problema con delay è stato corretto in OS X 10.11 El Capitan.

@ 2oh1, hai lidea di base giusta nella tua risposta, ma qui” una risposta completa e corretta:

Lunico modo ragionevole per aggirare questo problema è invocare “ritardo” allinterno di un ciclo che assicuri che la durata desiderata trascorra prima di continuare. Il modo migliore per farlo è sovrascrivere “ritardo” con un gestore personalizzato:

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 

Ciò ti consente di lasciare invariato il resto dello script e puoi utilizzare “delay” normalmente, ad esempio

delay 5 display alert "I like cake!" 

[NOTA: Normalmente, il gestore personalizzato userebbe “continue delay duration” per invocare il “ritardo” integrato, ma ho scoperto che, sebbene funzioni in Script Editor, restituisce un errore quando viene utilizzato allinterno di unapplet (“Impossibile continuare il ritardo. (-1708) “). Ho aggirato il problema dicendo direttamente ad AppleScript di gestire il comando delay invece di utilizzare “continue” per arrivarci.]

Il problema è che delay elabora lutente input durante la pausa dello script, in modo da poter ancora fare clic sui menu o sulle finestre visualizzate da unapplet e cè un bug (corretto nella 10.11) in cui linput dellutente fa sì che delay non attenda durata completa prima di riprendere lesecuzione dello script. Se non interagisci con lapplet, delay funziona correttamente.

Commenti

  • È tutto di questo un bug, o cè una ragione per cui il ritardo funziona in questo modo con Yosemite?
  • È un bug che il ritardo non è ‘ ritardare.
  • È ‘ è così strano. Stavo armeggiando con uno script di mele che utilizza il ritardo laltra notte e improvvisamente, il ritardo ha funzionato di nuovo correttamente. Ho pensato che il bug fosse stato risolto . Unora dopo, anche se non era cambiato nulla, il bug era tornato. ‘ sono veramente sconcertato. Non ‘ importa però . Io ‘ utilizzo una variabile per impostare lora e il ritardo fino a cinque minuti dopo (ad esempio) e ‘ funziona perfettamente Quindi … problema risolto, ma questo non ‘ spiega perché il problema esiste. Interessante, interessante, interessante.
  • Perché Apple ha sbagliato. Apple il software è molto meno affidabile da quando hanno iniziato a rilasciare OS X ogni anno. Mi mancano le versioni minori di OS X superiori (come 10.6.8) in cui il sistema operativo era solido come una roccia. Semplicemente non ‘ ottieni più quel tipo di esperienza.
  • Se ‘ è un bug (che accetto con), perché ‘ non è ancora risolto, mi chiedo. Qualcuno qui ha fatto un rapporto radar? Potresti quindi pubblicare il suo ID? (o / anche postare su openradar.me)

Risposta

Mentre combattevo con lo stesso problema mi sono imbattuto questa risposta a una domanda non correlata e ha deciso di provarla e sembra funziona per me.

Sostituisci delay 5 con do shell script "/bin/sleep 5" e ottieni lo stesso risultato.

Commenti

  • Grazie per la condivisione! Come ho detto prima, ‘ non sono in grado di testarlo perché, per motivi che non hanno senso per me, il ritardo 5 funziona come dovrebbe per me in questo momento (ho appena testato ancora un attimo fa). Non ho idea del motivo per cui a volte funziona e talvolta fallisce.’ è così strano. Ho finito per utilizzare una soluzione alternativa in cui ottengo lora corrente e la imposto come variabile, quindi metto in pausa lo script fino a quando lora non è variabile più un minuto (per un minuto di ritardo, ovviamente). È ‘ goffo, ma ‘ ha funzionato perfettamente per mesi, mentre un semplice ritardo è stato intermittente. Uff.
  • Sto eseguendo la 10.10.5 e questa soluzione non funziona e blocca anche lo script per la durata del sonno
  • @Greg: Se “blocca lo script” per la durata del sonno, quindi ‘ funziona. /bin/sleep attende la durata del sonno e non ritorna fino al termine. Al contrario, il comando ‘ incorporato di AppleScript delay gestisce gli eventi di input dellutente mentre lo script è in pausa. (Ed è qui che si trova il bug: se cè un input da tastiera dellutente, delay continua lesecuzione dello script prima che la durata del ritardo sia stata completata.)

Risposta

Non sto dicendo che questa sia la soluzione migliore, ma sembra che abbia risolto il mio problema. Invece di usare un semplice ritardo, che viene ignorato per ragioni che non capisco, sono passato alla lettura dellora e al ciclo continuo fino a quando non viene raggiunta una nuova ora (usa ancora un ritardo, ma non importa se ignora il ritardo poiché lo script non continua fino a quando il tempo è raggiunto).

# 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 

Non vedo ancora lora di sapere perché il ritardo viene ignorato (o notevolmente accelerato?! ??), ma il lavoro fatto, goffo comè.

Commenti

  • Il ” ritardo ” non è ‘ ” velocizzato ” , ‘ viene interrotto. Durante il ritardo, si trova in un ciclo che controlla se ci sono eventi di input da tastiera in modo che possa verificare il periodo di comando. Apparentemente sta uscendo erroneamente dal ciclo di ritardo quando viene rilevato un input utente.
  • Interessante! ‘ sto scoprendo che ‘ viene ignorato (accelerato? Interrotto?) Anche quando il mio Mac è inattivo, ma non ‘ Non so perché.
  • Una volta che un evento di input dellutente è nella coda eventi, delay continuerà a essere interrotto finché qualcosa non gestisce gli eventi e li rimuove dalla coda.

Risposta

Ho trovato un lavoro- in un post del forum in tedesco. Aggiungi queste righe allinizio dello script:

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

Commenti

  • I ‘ ho problemi a testare la tua risposta perché, per qualsiasi motivo, il ritardo attualmente funziona come previsto sul mio Mac. Non ho idea del perché. ‘ corro 10.10.3. Forse Apple ha risolto questo bug? O forse ‘ è solo un problema intermittente che non ‘ influisce sul mio Mac in questo momento. Uffa. Come ho detto sopra, però, la mia soluzione alternativa è fare in modo che Applescript ottenga lora corrente e quindi rimandi fino allora corrente più x.
  • Sto eseguendo anche 10.10.3 e vedo ancora il problema. Poiché non tutti vedono il problema, ‘ è probabilmente intermittente o correlato a software di terze parti o a determinate impostazioni delle preferenze. Chi lo sa. A proposito, la tua soluzione ha probabilmente lo svantaggio che lapp continua a utilizzare il 100% del tempo della CPU durante lattesa, mentre il comportamento corretto del ritardo è mettere lapp in sospensione per quella durata, utilizzando quindi meno energia.
  • Sto eseguendo la 10.10.5 e questa soluzione non funziona.
  • @ThomasTempelmann: il problema si verifica quando cè linput dellutente. Se ‘ non fai clic o digiti mentre lo script è in esecuzione, il bug non è ‘ attivato.
  • Si noti che questa soluzione fa sì che lapplicazione si blocchi effettivamente per la durata del sonno. delay elabora linput dellutente mentre lo script è in pausa, quindi puoi comunque interagire con menu e finestre, ad esempio.

Risposta

carzyj aveva quella che considero la risposta migliore, ma se combinato con il metodo di Chris Page, ottieni:

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

Puoi commentare da “on delay” a “end delay” per ripristinare il ritardo originale.

Commenti

  • I ho anche fatto una modifica del codice simile, prima di vederlo. Sto eseguendo la 10.10.5 e questa soluzione non funziona e blocca anche lo script per la durata del sonno.

Risposta

questa è una modifica alla soluzione @ chris-page

Sembra essere un equilibrio tra la reattività e lacquisizione accurata del ritardo.

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 

Ma invece di dire ad Applescript di ritardare per la durata complessiva, gli diciamo semplicemente di ritardare per una frazione di periodo della durata. se il periodo è inferiore a quello consentito dalla mela (1/60 di secondo), impostiamolo semplicemente su quel delta. Che possiamo mantenere un po di reattività, ma comunque essere precisi. il sospetto è che a volte il ritardo non lo fa “t funziona in modo che il ciclo di ripetizione while manterrà il thread bloccato, ma in scenari di successo, vogliamo che il delta del ritardo sia breve in modo che il processo possa ancora essere interrotto

Commenti

  • Accorciare il ritardo richiesto non è necessario e può solo rallentare lesecuzione dello script e consumare più CPU durante lattesa. La mia versione chiama semplicemente il ritardo fino allo scadere dellintera durata desiderata, consentendo a delay di ritardare il più possibile prima di continuare lesecuzione.
  • Tieni presente che poiché questa risposta è stato pubblicato, ho aggiornato il mio codice per utilizzare delay endTime - (current date) invece di delay duration, il che garantisce che se delay non ‘ t viene interrotto, ‘ non metterà in pausa lo script più del tempo richiesto originariamente , che potrebbe essere ciò a cui stavi cercando di rispondere con questa risposta.

Risposta

Quindi, per mettere tutto insieme, credo che Chris intenda questo:

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 

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *