Obs: Problemet med delay
fixades i OS X 10.11 El Capitan.
Ända sedan jag uppgraderade till Yosemite har Applescripts som använder förseningar slutat fungera . Hur kan jag åtgärda detta?
Här är världens enklaste äppelskript för ett enkelt exempel:
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
Det bör ta 30 sekunder att slutföra. Om jag kör den i Script Editor (tidigare Applescript Editor) tar det 30 sekunder att slutföra. Men om jag sparar det här skriptet som en app, när jag startar appen ignoreras förseningarna och appen tar en bråkdel av en sekund att slutföra.
Hur kan jag tvinga Applescript att fördröja för en viss mängd innan du går vidare till nästa steg? Är det här en Yosemite-glitch? Finns det en tillförlitlig lösning?
Kommentarer
- Detta fungerar som förväntat på min Mac (10.10.1)
- Någon idé vad gör att det inte fungerar på mitt? För att klargöra: det fungerar i Script Editor, men om jag sparar manuset som en app och sedan startar appen ignoreras förseningarna. Det ’ är det konstigaste.
- Jag har samma problem den 10.10.3
- Rapporterade till Apple: openradar.me/21588747
- Problemet åtgärdades i OS X 10.11 El Capitan.
Svar
Obs: Problemet med delay
fixades i OS X 10.11 El Capitan.
@ 2oh1, du har rätt grundidé i ditt svar, men här” är ett fullständigt och korrekt svar:
Det enda rimliga sättet att kringgå detta är att åberopa ”fördröjning” i en slinga som säkerställer att den önskade varaktigheten löper ut innan du fortsätter. Det bästa sättet att göra detta är att åsidosätta ”fördröjning” med en anpassad hanterare:
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
Detta gör att du kan lämna resten av ditt skript oförändrat och du kan använda ”fördröjning” normalt, t.ex.
delay 5 display alert "I like cake!"
[OBS: Normalt skulle den anpassade hanteraren använda ”fortsätt fördröjningstid” för att åberopa den inbyggda ”fördröjningen”, men jag fann att även om detta fungerar i Script Editor, returnerar det ett fel när det används i en applet (”Kan inte fortsätta fördröjningen. (-1708) ”). Jag arbetade runt den frågan genom att direkt be AppleScript att hantera fördröjningskommandot istället för att använda ”fortsätt” för att komma dit.]
Problemet är att delay
behandlar användaren inmatning medan du pausar skriptet så att du fortfarande kan klicka på menyer eller fönster som visas i en applet, och det finns ett fel (fixat i 10.11) där användarinmatningen gör att delay
inte väntar på full varaktighet innan skriptkörningen återupptas. Om du inte interagerar med appleten fungerar delay
korrekt.
Kommentarer
- Är allt av detta ett fel, eller finns det en anledning till att fördröjning fungerar så här med Yosemite?
- Det är ett fel som fördröjningen inte ’ t fördröjer.
- Det ’ är så konstigt. Jag pratade med ett äppelskript som använder fördröjning den andra natten, och plötsligt fungerade fördröjningen igen korrekt. Jag antog att felet hade rättats . En timme senare, även om ingenting hade förändrats, var felet tillbaka. Jag ’ är verkligen förvirrad. Det spelar ingen roll ’ . Jag ’ använder en variabel för att ställa in tid och fördröjning till fem minuter senare (till exempel), och den ’ fungerar perfekt Så … problemet löst, men det förklarar inte ’ varför problemet existerar. Intressant, intressant, intressant.
- Eftersom Apple dumt. Apple programvara är mycket mindre tillförlitlig sedan de började släppa OS X årligen. Jag saknar de högre OS X-mindre versionerna (som 10.6.8) där operativsystemet var solid. Du får bara ’ inte den typen av upplevelse längre.
- Om det ’ är ett fel (som jag håller med om med), varför är det inte ’ t, undrar jag. Har någon här gjort en radarrapport? Skulle du gärna lägga upp dess ID? (eller / posta också på openradar.me)
Svar
Medan jag kämpade mot samma problem stötte jag på detta svar på en inte så relaterad fråga och bestämde oss för att prova det och det verkar arbeta för mig.
Ersätt delay 5
med do shell script "/bin/sleep 5"
och få samma resultat.
Kommentarer
- Tack för att du delar! Som jag sa tidigare ovan kan jag ’ inte testa detta eftersom fördröjning 5 av skäl som inte är vettiga för mig fungerar som den ska för mig just nu (jag testade just det igen för en stund sedan). Jag har ingen aning om varför detta ibland fungerar och ibland misslyckas.Det ’ är så konstigt. Jag slutade använda en lösning där jag får den aktuella tiden och ställer in den som en variabel och pausar sedan skriptet tills tiden är variabel plus en minut (för en minuts fördröjning, uppenbarligen). Det ’ är klumpigt, men det ’ har fungerat felfritt i flera månader, medan en enkel fördröjning har varit intermittent. Ugh.
- Jag kör 10.10.5 och den här lösningen fungerar inte och låser också skriptet under sömnens varaktighet
- @Greg: Om det ”låser skriptet” för sömnens varaktighet, då fungerar den ’.
/bin/sleep
väntar på vilolängden och återgår inte förrän den är klar. Däremot hanterar AppleScript ’ s inbyggdadelay
kommandon för användarinmatning medan skriptet är pausat. (Vilket är där buggen ligger: om det finns tangentbordets inmatning fortsätterdelay
körningen av skriptet innan fördröjningstiden har slutförts.)
Svar
Jag säger inte att det här är den bästa lösningen, men det verkar ha löst mitt problem. Istället för att använda en enkel fördröjning, som ignoreras Av skäl som jag inte förstår, har jag bytt till att få tiden och loopa tills en ny tid har uppnåtts (den använder fortfarande en fördröjning, men det spelar ingen roll om den ignorerar förseningen eftersom skriptet inte fortsätter tills tiden uppnås).
# 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
Jag vill fortfarande veta varför fördröjning ignoreras (eller dramatiskt påskyndas?! ??), men detta blir jobbet gjort, klumpigt som det är.
Kommentarer
- ” fördröjning ” kommandot är inte ’ t är ” ökar ” , det ’ avbryts. Medan det fördröjs sitter det i en slinga och kontrollerar om det finns några tangentbordsinmatningshändelser så att det kan kontrollera kommandotiden. Tydligen går det felaktigt ut ur fördröjningsslingan när någon användarinmatning detekteras.
- Intressant! Jag ’ upptäcker att det ’ ignoreras (påskyndas? Avbryts?) Även när min Mac sitter i tomgång, men jag vet inte ’ vet inte varför.
- När en användarinmatningshändelse är i händelsekön fortsätter
delay
till avbryts tills något hanterar händelserna och tar bort dem från kön.
Svar
Jag hittade ett arbete- runt i ett tyskt foruminlägg . Lägg till dessa rader längst upp i ditt skript:
use framework "Foundation" use scripting additions current application"s NSThread"s sleepForTimeInterval:1
Kommentarer
- I ’ Jag har problem med att testa ditt svar eftersom, av någon anledning, förseningen för närvarande fungerar som förväntat på min Mac. Jag har ingen aning om varför. Jag ’ kör 10.10.3. Kanske fixade Apple detta fel? Eller kanske är det ’ bara ett intermittent problem som inte ’ påverkar min Mac just nu. Usch. Som jag sa ovan är min lösning dock att Applescript får aktuell tid och sedan fördröjer tills aktuell tid plus x.
- Jag kör också 10.10.3 och ser fortfarande problemet. Eftersom inte alla ser problemet är det ’ förmodligen intermittent eller relaterat till programvara från tredje part eller till vissa inställningar för preferenser. Vem vet. BTW, ditt arbete har förmodligen nackdelen att appen fortsätter att använda 100% CPU-tid medan den väntar, medan det korrekta fördröjningsbeteendet är att låta appen sova under den tiden och därmed använda mindre ström.
- Jag kör 10.10.5 och den här lösningen fungerar inte.
- @ThomasTempelmann: Problemet uppstår när det finns användarinmatning. Om du inte klickar eller skriver ’ medan skriptet körs, är felet inte ’ t utlöst.
- Observera att denna lösning gör att applikationen faktiskt fryser under sömnens varaktighet.
delay
bearbetar användarinmatning medan skriptet är pausat, så att du fortfarande kan interagera med menyer och fönster, till exempel.
Svar
carzyj hade det som jag anser vara det bästa svaret, men när det kombineras med Chris Pays metod får du:
on delay duration do shell script "/bin/sleep " & duration end delay
Du kan kommentera ”fördröjning” till ”slutfördröjning” för att återgå till den ursprungliga fördröjningen.
Kommentarer
- I gjorde också en liknande kodändring innan jag såg den här. Jag kör 10.10.5 och den här lösningen fungerar inte och låser också skriptet under sömnens varaktighet.
Svar
detta är en modifiering av @ chris-sida-lösning
Det verkar vara en balans mellan lyhördhet och exakt fånga förseningen.
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
Men istället för att be Applescript att fördröja under den totala varaktigheten, säger vi bara att den ska fördröjas under en bråkperiod av varaktigheten. om perioden är mindre än vad äpple tillåter (1/60 av en sekund), låt oss bara ställa in det till det deltaet. Att vi kan behålla en viss lyhördhet, men ändå vara korrekt. Misstanken är att ibland fördröjning inte gör det arbeta så att repetitionen medan slingan håller tråden låst, men i framgångsscenarier vill vi att fördröjningsdeltaet är kort så att processen fortfarande kan avbrytas
Kommentarer
- Att förkorta den begärda fördröjningen är onödig och kan bara göra att skriptet går långsammare och förbrukar mer CPU medan du väntar. Min version kallar bara fördröjning tills hela önskad varaktighet har gått, så att
delay
kan fördröja så mycket som möjligt innan den fortsätter körningen. - Observera att eftersom det här svaret publicerades uppdaterade jag min kod för att använda
delay endTime - (current date)
istället fördelay duration
, vilket säkerställer att omdelay
avbryts inte ’ t det vann ’ t pausar manuset längre än den ursprungligen begärda tiden , vilket kan ha varit det du försökte ta itu med det här svaret.
Svar
Så att uttrycka allt tillsammans tror jag att Chris menar detta:
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