自切换到优胜美地以来,AppleScript“延迟”命令不起作用


10

注意:问题delay已在OS X 10.11 El Capitan中修复。

自从我升级到优胜美地以来,使用延迟的Applescript停止运行。我怎样才能解决这个问题?

举一个简单的例子,这是世界上最简单的Applescript:

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

这需要30秒才能完成。如果我在脚本编辑器(以前称为Applescript编辑器)中运行它,则需要30秒才能完成。但是,如果我将此脚本另存为应用程序,则在启动该应用程序时,延迟将被忽略,并且该应用程序将花费一秒钟的时间来完成。

在进入下一步之前,如何强制Applescript延迟指定的时间?这是优胜美地故障吗?有可靠的解决方法吗?


这可以在我的Mac(10.10.1)上正常运行
markhunte 2014年

知道是什么原因导致它无法在我的机器上工作吗?需要说明的是:它可以在脚本编辑器中使用,但是如果我将脚本另存为应用程序,然后启动该应用程序,则将忽略延迟。这是最奇怪的事情。
2014年

我在10.10.3上遇到了同样的问题
Thomas Tempelmann

报告给苹果公司:openradar.me/21588747
Thomas Tempelmann

1
此问题已在OS X 10.11 El Capitan中修复。
克里斯·佩奇

Answers:


7

注意:问题delay已在OS X 10.11 El Capitan中修复。

@ 2oh1,您的答案中有正确的基本概念,但这是一个完整而正确的答案:

解决此问题的唯一合理方法是在循环中调用“延迟”,以确保在继续操作之前经过了所需的持续时间。最好的方法是使用自定义处理程序覆盖“延迟”:

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

这使您可以保留脚本的其余部分不变,并且可以正常使用“延迟”,例如,

delay 5
display alert "I like cake!"

[注意:通常,自定义处理程序将使用“持续延迟持续时间”来调用内置的“延迟”,但是我发现,尽管这在脚本编辑器中有效,但在applet中使用时会返回错误(“可以” t继续延迟。(-1708)”)。我通过直接告诉AppleScript处理delay命令而不是使用“ continue”到达那里来解决该问题。

问题在于,delay在暂停脚本的同时会处理用户输入,因此您仍然可以单击小程序显示的菜单或窗口,并且存在一个错误(已在10.11中修复),该错误导致用户输入delay在恢复脚本执行之前未等待完整的持续时间。如果您不与小程序交互,则delay可以正常工作。


所有这些都是错误,还是延迟与优胜美地一起工作的原因?
2015年

延迟没有延迟是一个错误。
克里斯·佩奇

真奇怪 我正在修改一个使用前一天晚上延迟的小程序,突然之间,延迟再次正常运行。我认为该错误已修复。一个小时后,即使一切都没有改变,该错误又回来了。我真的很困惑。没关系。我正在使用一个变量来设置时间和延迟,直到五分钟后(例如),它运行良好。所以...问题解决了,但这并不能解释问题为什么存在。有趣,有趣,有趣。
2015年

1
因为苹果无聊。苹果软件的可靠性要差得多,因为它们开始每年发布OSX。我想念更高版本的OS X次要版本(如10.6.8),那里的操作系统坚如磐石。您只是不再有那种经验。
William T Froggard

我想知道,如果这是一个错误(我同意),为什么还不能解决?这里有人有雷达报告吗?然后,请您发布其ID?(或/也在openradar.me上发布)
Thomas Tempelmann

5

在解决同一问题时,我遇到了一个不太相关的问题的答案因此决定尝试一下,它似乎对我有用。

只需替换delay 5do shell script "/bin/sleep 5",即可获得相同的结果。


感谢分享!就像我在上面前面说的,我无法测试它,因为出于我认为没有道理的原因,延迟5正在按我现在的方式工作(我刚才刚刚对其进行了测试)。我不知道为什么有时这样做有时失败。真奇怪 我最终使用了一种变通方法,在该方法中,我可以获取当前时间并将其设置为变量,然后暂停脚本,直到该时间为变量加一分钟(显然是1分钟的延迟)。它虽然笨拙,但已连续数月完美运行,而一次简单的延迟却是断断续续的。啊。
2015年

我正在运行10.10.5,此解决方案无法正常工作,并且还会在睡眠期间锁定脚本
Greg 2015年

@Greg:如果它在睡眠期间“锁定了脚本”,则说明它正在工作。/bin/sleep等待睡眠时间,直到完成才返回。相反,AppleScript的内置delay命令在脚本暂停时处理用户输入事件。(错误所在的位置:如果有用户键盘输入,请delay在延迟持续时间完成之前继续执行脚本。)
克里斯·佩奇

3

我并不是说这是最好的解决方案,但似乎已经解决了我的问题。我不再使用简单的延迟(由于我不明白的原因而被忽略),我改用获取时间并循环直到到达新的时间(它仍然使用延迟,但是忽略则无所谓延迟,因为脚本要到指定时间才会继续执行)。

# 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

我仍然很想知道为什么延迟被忽略(或者大大加快了速度!! ??),但这可以完成工作,而且笨拙。


“延迟”命令没有被“加速”,而是被中断了。延迟时,它会循环检查是否有键盘输入事件,以便可以检查Command-Period。显然,当检测到任何用户输入时,它错误地退出了延迟循环。
克里斯·佩奇

有趣!我发现即使我的Mac闲置时,它也被忽略了(加快了速度?被打断了?),但是我不知道为什么。
2015年

一旦用户输入事件进入事件队列,delay它将继续被中断,直到有人处理事件并将其从队列中删除为止。
克里斯·佩吉

2

我在德语论坛帖子中找到了解决方法。将这些行添加到脚本顶部:

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

我无法测试您的答案,因为无论出于何种原因,延迟都正在Mac上按预期运行。我不知道为什么。我正在运行10.10.3。也许苹果修复了这个错误?或者,也许这只是一个间歇性问题,目前还没有影响我的Mac。啊。正如我上面所说的,我的解决方法是让Applescript获取当前时间,然后延迟到当前时间加上x。
2015年

我也正在运行10.10.3,但仍然看到该问题。由于并非所有人都看到此问题,因此它可能是间歇性的,或与第三方软件或某些首选项设置有关。谁知道。顺便说一句,您的变通方法可能具有以下缺点:应用程序在等待时始终使用100%的CPU时间,而适当的延迟行为是使该应用程序在该持续时间内进入睡眠状态,从而消耗较少的电量。
Thomas Tempelmann

我正在运行10.10.5,并且此解决方案不起作用。
格雷格

@ThomasTempelmann:当有用户输入时,会发生此问题。如果在脚本运行时未单击或键入,则不会触发该错误。
克里斯·

请注意,此解决方案会使应用程序在睡眠期间实际上冻结。delay在脚本暂停时处理用户输入,因此,例如,您仍然可以与菜单和窗口进行交互。
克里斯·佩奇

0

我认为carzyj是最好的答案,但是当与Chris Page的方法结合使用时,您会得到:

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

您可以通过“结束延迟”注释掉“延迟”,以恢复为原始延迟。


在看到此代码之前,我还进行了类似的代码修改。我正在运行10.10.5,此解决方案不起作用,并且在睡眠期间还会锁定脚本。
格雷格

0

这是对@ chris-page解决方案的修改

这似乎是响应性和准确捕获延迟之间的平衡。

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

但是,我们并没有告诉Applescript延迟整个持续时间,而只是告诉它延迟了整个持续时间的一小部分。如果周期小于苹果允许的时间(1/60秒),那么我们就将其设置为该增量。我们可以保持一些响应能力,但仍然是准确的。令人怀疑的是,有时延迟不起作用,所以repeat while循环将使线程锁定,但是在成功的情况下,我们希望延迟增量较短,以便仍然可以中断进程


缩短请求的延迟是不必要的,并且只会使脚本运行缓慢并在等待时消耗更多CPU。我的版本仅调用延迟,直到整个所需的持续时间过去为止,从而允许delay在继续执行之前尽可能地延迟。
克里斯·佩吉

请注意,自从发布此答案以来,我更新了我的代码以使用delay endTime - (current date)代替delay duration,这可以确保如果delay 被中断,它不会暂停脚本的时间不会超过原始请求的时间,这可能就是您要尝试的时间用这个答案解决。
克里斯·佩吉

0

因此,综上所述,我相信克里斯的意思是:

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.