Der AppleScript-Befehl "delay" funktioniert seit dem Wechsel zu Yosemite nicht mehr


10

Hinweis: Das Problem mit delaywurde in OS X 10.11 El Capitan behoben.

Seit ich auf Yosemite aktualisiert habe, funktionieren Applescripts, die Verzögerungen verwenden, nicht mehr. Wie kann ich das beheben?

Hier ist das einfachste Applescript der Welt, um ein einfaches Beispiel zu nennen:

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

Dies sollte 30 Sekunden dauern. Wenn ich es im Skript-Editor (früher Applescript-Editor) ausführe, dauert der Vorgang 30 Sekunden. Wenn ich dieses Skript jedoch als App speichere, werden beim Starten der App die Verzögerungen ignoriert und die App benötigt einen Bruchteil einer Sekunde.

Wie kann ich Applescript zwingen, eine bestimmte Zeitspanne zu verzögern, bevor ich mit dem nächsten Schritt fortfahre? Ist das ein Yosemite-Fehler? Gibt es eine zuverlässige Problemumgehung?


Dies funktioniert wie erwartet auf meinem Mac (10.10.1)
Markhunte

Irgendeine Idee, warum es bei mir nicht funktioniert? Zur Verdeutlichung: Es funktioniert im Skript-Editor. Wenn ich das Skript jedoch als App speichere und dann die App starte, werden die Verzögerungen ignoriert. Es ist das Seltsamste.
2oh1

Ich habe das gleiche Problem am 10.10.3
Thomas Tempelmann


1
Dieses Problem wurde in OS X 10.11 El Capitan behoben.
Chris Seite

Antworten:


7

Hinweis: Das Problem mit delaywurde in OS X 10.11 El Capitan behoben.

@ 2oh1, Sie haben die richtige Grundidee in Ihrer Antwort, aber hier ist eine vollständige und korrekte Antwort:

Die einzig vernünftige Möglichkeit, dies zu umgehen, besteht darin, "Verzögerung" innerhalb einer Schleife aufzurufen, die sicherstellt, dass die gewünschte Dauer vergeht, bevor Sie fortfahren. Der beste Weg, dies zu tun, besteht darin, "Verzögerung" mit einem benutzerdefinierten Handler zu überschreiben:

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

Auf diese Weise können Sie den Rest Ihres Skripts unverändert lassen und "Verzögerung" normal verwenden, z.

delay 5
display alert "I like cake!"

[HINWEIS: Normalerweise verwendet der benutzerdefinierte Handler "Verzögerungsdauer fortsetzen", um die integrierte "Verzögerung" aufzurufen. Ich habe jedoch festgestellt, dass dies zwar im Skript-Editor funktioniert, bei Verwendung in einem Applet jedoch einen Fehler zurückgibt ("Kann"). t Verzögerung fortsetzen. (-1708) ”). Ich habe dieses Problem umgangen, indem ich AppleScript direkt angewiesen habe, den Verzögerungsbefehl zu verarbeiten, anstatt "Weiter" zu verwenden, um dorthin zu gelangen.]

Das Problem besteht darin, dass delayBenutzereingaben verarbeitet werden, während das Skript angehalten wird, sodass Sie weiterhin auf Menüs oder Fenster klicken können, die von einem Applet angezeigt werden. Es gibt einen Fehler (in 10.11 behoben), bei dem Benutzereingaben dazu führen delay, dass nicht die gesamte Dauer gewartet wird, bevor die Skriptausführung fortgesetzt wird . Wenn Sie nicht mit dem Applet interagieren, delayfunktioniert es ordnungsgemäß.


Ist das alles ein Fehler oder gibt es einen Grund, warum die Verzögerung bei Yosemite so funktioniert?
2oh1

Es ist ein Fehler, dass Verzögerung nicht verzögert.
Chris Page

Es ist so komisch. Ich bastelte an einem Applescript, das neulich Nacht Verzögerung verwendet, und plötzlich funktionierte Verzögerung wieder richtig. Ich nahm an, dass der Fehler behoben war. Eine Stunde später war der Fehler zurück, obwohl sich nichts geändert hatte. Ich bin wirklich verblüfft. Es ist aber egal. Ich verwende eine Variable, um die Zeit und die Verzögerung bis zum Beispiel fünf Minuten später einzustellen, und sie funktioniert einwandfrei. Also ... Problem gelöst, aber das erklärt nicht, warum das Problem besteht. Interessant, interessant, interessant.
2oh1

1
Weil Apple vermasselt hat. Apple-Software ist viel weniger zuverlässig, da OS X jährlich veröffentlicht wird. Ich vermisse die höheren OS X-Nebenversionen (wie 10.6.8), in denen das Betriebssystem absolut solide war. Solche Erfahrungen macht man einfach nicht mehr.
William T Froggard

Wenn es ein Fehler ist (dem ich zustimme), warum ist das nicht immer noch nicht behoben, frage ich mich. Hat hier jemand einen Radarbericht gemacht? Würden Sie dann bitte die ID posten? (oder / oder auch auf openradar.me posten)
Thomas Tempelmann

5

Während ich mit demselben Problem kämpfte, stieß ich auf diese Antwort auf eine nicht so verwandte Frage und beschloss, es zu versuchen, und es scheint für mich zu funktionieren.

Ersetzen Sie einfach delay 5mit do shell script "/bin/sleep 5"und das gleiche Ergebnis.


Danke für das Teilen! Wie ich oben bereits sagte, kann ich dies nicht testen, da aus Gründen, die für mich keinen Sinn ergeben, Delay 5 gerade so funktioniert, wie es für mich sein sollte (ich habe es erst vor einem Moment erneut getestet). Ich habe keine Ahnung, warum dies manchmal funktioniert und manchmal fehlschlägt. Es ist so komisch. Am Ende habe ich eine Problemumgehung verwendet, bei der ich die aktuelle Zeit abrufe und als Variable festlege und dann das Skript anhalte, bis die Zeit variabel plus eine Minute ist (natürlich mit einer Verzögerung von 1 Minute). Es ist klobig, aber es hat monatelang einwandfrei funktioniert, während eine einfache Verzögerung zeitweise aufgetreten ist. Pfui.
2oh1

Ich verwende 10.10.5 und diese Lösung funktioniert nicht und sperrt auch das Skript für die Dauer des Schlafes
Greg

@ Greg: Wenn es das Skript für die Schlafdauer sperrt, dann funktioniert es. /bin/sleepwartet auf die Schlafdauer und kehrt erst zurück, wenn sie abgeschlossen ist. Im Gegensatz dazu verarbeitet der in AppleScript integrierte delayBefehl Benutzereingabeereignisse, während das Skript angehalten wird. (Hier liegt der Fehler: Wenn eine Benutzertastatur eingegeben wird, wird delaydie Skriptausführung fortgesetzt, bevor die Verzögerungsdauer abgelaufen ist.)
Chris Seite

3

Ich sage nicht, dass dies die beste Lösung ist, aber es scheint mein Problem gelöst zu haben. Anstatt eine einfache Verzögerung zu verwenden, die aus Gründen, die ich nicht verstehe, ignoriert wird, habe ich auf das Abrufen der Zeit und das Schleifen umgestellt, bis eine neue Zeit erreicht ist (es wird immer noch eine Verzögerung verwendet, aber es spielt keine Rolle, ob sie ignoriert wird Die Verzögerung, da das Skript erst nach Erreichen der Zeit fortgesetzt wird.

# 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

Ich möchte immer noch wissen, warum Verzögerungen ignoriert werden (oder dramatisch beschleunigt werden ?! ??), aber das erledigt den Job, ungeschickt wie er ist.


Der Befehl "Verzögerung" wird nicht "beschleunigt", sondern unterbrochen. Während der Verzögerung befindet es sich in einer Schleife und prüft, ob Tastatureingabeereignisse vorhanden sind, damit es nach der Befehlsperiode suchen kann. Anscheinend verlässt es die Verzögerungsschleife fälschlicherweise, wenn Benutzereingaben erkannt werden.
Chris Seite

Interessant! Ich stelle fest, dass es ignoriert wird (beschleunigt? Unterbrochen?), Selbst wenn mein Mac im Leerlauf sitzt, aber ich weiß nicht warum.
2oh1

Sobald sich ein Benutzereingabeereignis in der Ereigniswarteschlange befindet, delaywird es weiter unterbrochen, bis etwas die Ereignisse behandelt und sie aus der Warteschlange entfernt.
Chris Seite

2

Ich habe eine Problemumgehung in einem deutschen Forumsbeitrag gefunden . Fügen Sie diese Zeilen oben in Ihr Skript ein:

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

Ich habe Probleme beim Testen Ihrer Antwort, da die Verzögerung auf meinem Mac aus irgendeinem Grund derzeit wie erwartet funktioniert. Ich habe keine Idee warum. Ich laufe 10.10.3. Vielleicht hat Apple diesen Fehler behoben? Oder vielleicht ist es nur ein zeitweiliges Problem, das meinen Mac derzeit nicht betrifft. Pfui. Wie ich oben sagte, besteht meine Problemumgehung darin, dass Applescript die aktuelle Zeit abruft und dann bis zur aktuellen Zeit plus x verzögert.
2oh1

Ich verwende auch 10.10.3 und sehe das Problem immer noch. Da nicht jeder das Problem sieht, ist es wahrscheinlich zeitweise oder mit Software von Drittanbietern oder bestimmten Voreinstellungen verbunden. Wer weiß. Übrigens hat Ihre Problemumgehung wahrscheinlich den Nachteil, dass die App während des Wartens weiterhin 100% CPU-Zeit verbraucht, während das richtige Verzögerungsverhalten darin besteht, die App für diese Dauer in den Ruhezustand zu versetzen und dadurch weniger Strom zu verbrauchen.
Thomas Tempelmann

Ich verwende 10.10.5 und diese Lösung funktioniert nicht.
Greg

@ThomasTempelmann: Das Problem tritt auf, wenn Benutzereingaben vorliegen. Wenn Sie nicht klicken oder tippen, während das Skript ausgeführt wird, wird der Fehler nicht ausgelöst.
Chris Seite

Beachten Sie, dass diese Lösung bewirkt, dass die Anwendung für die Dauer des Schlafes tatsächlich einfriert. delayverarbeitet Benutzereingaben, während das Skript angehalten ist, sodass Sie beispielsweise weiterhin mit Menüs und Fenstern interagieren können.
Chris Seite

0

carzyj hatte meiner Meinung nach die beste Antwort, aber in Kombination mit der Methode von Chris Page erhalten Sie:

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

Sie können "on delay" bis "end delay" auskommentieren, um zur ursprünglichen Verzögerung zurückzukehren.


Ich habe auch eine ähnliche Code-Änderung vorgenommen, bevor ich dies gesehen habe. Ich verwende 10.10.5 und diese Lösung funktioniert nicht und sperrt auch das Skript für die Dauer des Ruhezustands.
Greg

0

Dies ist eine Modifikation der @ chris-page-Lösung

Es scheint ein Gleichgewicht zwischen Reaktionsfähigkeit und genauer Erfassung der Verzögerung zu sein.

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

Aber anstatt Applescript anzuweisen, sich um die Gesamtdauer zu verzögern, sagen wir ihm nur, dass es sich um einen Bruchteil der Dauer verzögern soll. Wenn der Zeitraum kürzer ist als es der Apfel zulässt (1/60 Sekunde), setzen wir ihn einfach auf dieses Delta. Dass wir eine gewisse Reaktionsfähigkeit behalten und trotzdem genau sein können. Der Verdacht besteht darin, dass die Verzögerung manchmal nicht funktioniert, sodass die Wiederholung während der Schleife den Thread blockiert. In Erfolgsszenarien möchten wir jedoch, dass das Verzögerungsdelta kurz ist, damit der Prozess weiterhin unterbrochen werden kann


Das Verkürzen der angeforderten Verzögerung ist nicht erforderlich und kann nur dazu führen, dass das Skript langsamer ausgeführt wird und während des Wartens mehr CPU verbraucht wird. Meine Version ruft lediglich die Verzögerung auf, bis die gesamte gewünschte Dauer abgelaufen ist, sodass delayso viel wie möglich verzögert werden kann, bevor die Ausführung fortgesetzt wird.
Chris Seite

Beachten Sie, dass ich seit der Veröffentlichung dieser Antwort meinen Code so aktualisiert habe, dass er verwendet wird. delay endTime - (current date)Dadurch delay durationwird sichergestellt, dass das Skript nicht länger als die ursprünglich angeforderte Zeit angehalten wird, wenn Sie delay nicht unterbrochen werden. Dies war möglicherweise das, was Sie versucht haben Adresse mit dieser Antwort.
Chris Seite

0

Um alles zusammenzufassen, ich glaube, Chris meint das so:

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.