คำสั่ง "ล่าช้า" ของ AppleScript ไม่ทำงานเนื่องจากเปลี่ยนเป็นโยเซมิตี


10

หมายเหตุ:ปัญหาที่delayได้รับการแก้ไขใน OS X 10.11 El Capitan

ตั้งแต่ฉันอัปเกรดเป็น Yosemite แล้ว Applescripts ที่ใช้ความล่าช้าได้หยุดทำงาน ฉันจะแก้ไขสิ่งนี้ได้อย่างไร

นี่คือ 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 วินาทีเพื่อให้เสร็จสมบูรณ์ ถ้าฉันเรียกใช้ใน Script Editor (เดิมชื่อ Applescript Editor) จะใช้เวลา 30 วินาทีจึงจะเสร็จสมบูรณ์ แต่ถ้าฉันบันทึกสคริปต์นี้เป็นแอพเมื่อฉันเปิดแอพความล่าช้าจะถูกละเว้นและแอพใช้เวลาเพียงเสี้ยววินาทีในการดำเนินการให้เสร็จสมบูรณ์

ฉันจะบังคับให้ Applescript หน่วงเวลาตามระยะเวลาที่กำหนดก่อนที่จะไปยังขั้นตอนถัดไปได้อย่างไร นี่เป็นความผิดพลาดของโยเซมิตีหรือไม่? มีวิธีแก้ปัญหาที่เชื่อถือได้หรือไม่?


ทำงานได้ตามที่คาดหวังใน Mac ของฉัน (10.10.1)
markhunte

มีความคิดอะไรที่ทำให้มันไม่ทำงานบนของฉัน? เพื่อชี้แจง: ใช้งานได้ใน Script Editor แต่ถ้าฉันบันทึกสคริปต์เป็นแอพแล้วเปิดแอพความล่าช้าจะถูกละเว้น มันเป็นสิ่งที่แปลกประหลาดที่สุด
2oh1

ฉันมีปัญหาเดียวกันในวันที่ 10.10.3
Thomas Tempelmann

รายงานไปยัง Apple: openradar.me/21588747
Thomas Tempelmann

1
ปัญหานี้ได้รับการแก้ไขใน OS X 10.11 El Capitan
Chris Page

คำตอบ:


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!"

[หมายเหตุ: โดยปกติตัวจัดการแบบกำหนดเองจะใช้ "ระยะเวลาหน่วงเวลาการดำเนินต่อ" เพื่อเรียกใช้ "การหน่วงเวลา" ในตัว แต่ฉันพบว่าแม้ว่าการทำงานในตัวแก้ไขสคริปต์จะส่งกลับข้อผิดพลาดเมื่อใช้ภายในแอปเพล็ต ไม่ล่าช้าต่อไป (-1708)”) ฉันแก้ไขปัญหานั้นโดยตรงโดยแจ้งให้ AppleScript จัดการคำสั่งหน่วงเวลาแทนการใช้ "ดำเนินการต่อ" เพื่อไปที่นั่น]

ปัญหาคือการdelayประมวลผลอินพุตของผู้ใช้ในขณะที่หยุดสคริปต์ดังนั้นคุณยังคงสามารถคลิกที่เมนูหรือหน้าต่างที่แสดงโดยแอปเพล็ตและมีข้อผิดพลาด (แก้ไขใน 10.11) ที่การป้อนข้อมูลของผู้ใช้ทำให้delayไม่ต้องรอ . หากคุณไม่ได้ทำงานกับแอปเพล็ตdelayทำงานอย่างถูกต้อง


ทั้งหมดนี้เป็นข้อผิดพลาดหรือมีเหตุผลที่ล่าช้าในการทำงานแบบนี้กับโยเซมิตีหรือไม่?
2oh1

มันเป็นข้อผิดพลาดที่การหน่วงเวลาไม่ได้ล่าช้า
Chris Page

มันแปลกมาก ฉันกำลังซ่อมแซมแอปพลิเคชันที่ใช้ความล่าช้าในคืนก่อนและทันใดนั้นความล่าช้าก็ทำงานได้อย่างถูกต้องอีกครั้ง ฉันคิดว่าข้อผิดพลาดได้รับการแก้ไขแล้ว ชั่วโมงต่อมาแม้ว่าจะไม่มีอะไรเปลี่ยนแปลงข้อผิดพลาดก็กลับมา ฉันงงงันอย่างแท้จริง มันไม่สำคัญว่า ฉันใช้ตัวแปรเพื่อตั้งเวลาและล่าช้าจนถึงห้านาทีต่อมา (ตัวอย่าง) และมันก็ทำงานได้อย่างสมบูรณ์ ดังนั้น ... แก้ปัญหาแล้ว แต่นั่นไม่ได้อธิบายว่าทำไมถึงมีปัญหา น่าสนใจน่าสนใจน่าสนใจ
2oh1

1
เพราะแอปเปิ้ลโง่ ซอฟต์แวร์ Apple นั้นมีความน่าเชื่อถือน้อยกว่ามากตั้งแต่พวกเขาเริ่มปล่อย OS X ทุกปี ฉันคิดถึง OS X รุ่นรองที่สูงกว่า (เช่น 10.6.8) ซึ่งเป็นระบบปฏิบัติการที่แข็งแกร่ง คุณแค่ไม่ได้รับประสบการณ์แบบนั้นอีกต่อไป
William T Froggard

หากเป็นข้อผิดพลาด (ซึ่งฉันเห็นด้วย) ทำไมสิ่งนี้ถึงไม่ยังไม่ได้รับการแก้ไขฉันสงสัยว่า มีใครที่นี่ทำรายงานเรดาร์? คุณช่วยกรุณาโพสต์ ID ของมันได้ไหม (หรือ / ยังโพสต์บน openradar.me)
Thomas Tempelmann

5

ในขณะที่ต่อสู้กับปัญหาเดียวกันนี้ฉันได้พบคำตอบสำหรับคำถามที่ไม่เกี่ยวข้องดังนั้นจึงตัดสินใจลองและดูเหมือนจะใช้ได้สำหรับฉัน

เพียงแทนที่delay 5ด้วยdo shell script "/bin/sleep 5"และรับผลลัพธ์เดียวกัน


ขอบคุณสำหรับการแบ่งปัน! อย่างที่ฉันได้กล่าวไปแล้วข้างต้นฉันไม่สามารถทดสอบสิ่งนี้ได้เพราะด้วยเหตุผลที่ไม่สมเหตุสมผลกับฉันการล่าช้า 5 ทำงานได้อย่างที่ควรจะเป็นสำหรับฉันตอนนี้ (ฉันเพิ่งทดสอบอีกครั้งเมื่อไม่นานมานี้) ฉันไม่รู้ว่าทำไมบางครั้งมันถึงใช้ได้และบางครั้งก็ล้มเหลว มันแปลกมาก ฉันลงเอยด้วยการใช้วิธีแก้ปัญหาที่ฉันได้รับเวลาปัจจุบันและตั้งเป็นตัวแปรแล้วหยุดสคริปต์ชั่วคราวจนกว่าเวลาจะเป็นตัวแปรบวกหนึ่งนาที (สำหรับการหน่วงเวลา 1 นาทีชัด) มันเป็น clunky แต่มันทำงานได้อย่างไร้ที่ติเป็นเวลาหลายเดือนในขณะที่ความล่าช้าง่าย ๆ ไม่ต่อเนื่อง ฮึ.
2oh1

ฉันใช้งาน 10.10.5 และวิธีนี้ไม่สามารถใช้งานได้และยังล็อคสคริปต์ในช่วงเวลาพัก
Greg

@Greg: หาก“ ล็อคสคริปต์” ในช่วงเวลาพักเครื่องแสดงว่าทำงานได้ /bin/sleepรอช่วงเวลาพักเครื่องและจะไม่กลับจนกว่าจะเสร็จสิ้น ในทางตรงกันข้ามdelayคำสั่งในตัวของ AppleScript จะจัดการกับเหตุการณ์ที่ป้อนเข้าของผู้ใช้ในขณะที่สคริปต์หยุดชั่วคราว (ซึ่งเป็นที่ที่ข้อผิดพลาดอยู่: หากมีการป้อนข้อมูลแป้นพิมพ์ของผู้ใช้delayดำเนินการสคริปต์ต่อไปก่อนที่ระยะเวลาล่าช้าจะเสร็จสมบูรณ์)
Chris Page

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

ฉันยังคงอยากรู้ว่าทำไมความล่าช้าจึงถูกเพิกเฉย (หรือเร่งความเร็วขึ้นอย่างมาก?!) แต่สิ่งนี้ทำให้งานสำเร็จลุล่วงอย่างที่มันเป็น


คำสั่ง "ล่าช้า" ไม่ได้ถูก "เร่งความเร็ว" แต่ถูกขัดจังหวะ ในขณะที่การหน่วงเวลามันอยู่ในการตรวจสอบลูปว่ามีเหตุการณ์อินพุตคีย์บอร์ดใด ๆ หรือไม่เพื่อให้สามารถตรวจสอบช่วงเวลาของคำสั่ง เห็นได้ชัดว่ามันออกจากลูปล่าช้าอย่างไม่ถูกต้องเมื่อตรวจพบอินพุตของผู้ใช้
Chris หน้า

! ที่น่าสนใจ ฉันพบว่ามันถูกเพิกเฉย (ถูกขัดจังหวะ? ถูกขัดจังหวะ?) แม้ในขณะที่ Mac ของฉันไม่ได้ทำงาน แต่ฉันไม่รู้ว่าทำไม
2oh1

เมื่อเหตุการณ์ที่ผู้ใช้ป้อนอยู่ในคิวเหตุการณ์delayจะถูกขัดจังหวะต่อไปจนกว่าบางสิ่งจะจัดการกับเหตุการณ์และลบออกจากคิว
Chris Page

2

ผมพบว่าการทำงานรอบในเยอรมันโพสต์ฟอรั่ม เพิ่มบรรทัดเหล่านี้ไปด้านบนของสคริปต์ของคุณ:

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

ฉันมีปัญหาในการทดสอบคำตอบของคุณเนื่องจากความล่าช้าในขณะนี้ทำงานได้ตามที่คาดไว้ใน Mac ของฉันไม่ว่าด้วยเหตุผลใด ฉันมีความคิดว่าทำไมไม่มี. ฉันวิ่ง 10.10.3 บางที Apple แก้ไขข้อผิดพลาดนี้ หรืออาจเป็นเพียงปัญหาต่อเนื่องที่ไม่ส่งผลกระทบต่อ Mac ของฉันในขณะนี้ ฮึ. ดังที่ฉันได้กล่าวไว้ข้างต้นการแก้ปัญหาของฉันคือให้ Applescript รับเวลาปัจจุบันแล้วเลื่อนไปจนถึงเวลาปัจจุบันบวก x
2oh1

ฉันกำลังรัน 10.10.3 เช่นกันและยังคงเห็นปัญหาอยู่ เนื่องจากไม่ใช่ทุกคนที่เห็นปัญหาอาจเป็นช่วงหรือเกี่ยวข้องกับซอฟต์แวร์บุคคลที่สามหรือการตั้งค่าบางอย่าง ใครจะรู้. BTW การทำงานของคุณอาจมีข้อเสียที่แอพใช้เวลา CPU 100% ในขณะที่รออยู่ในขณะที่พฤติกรรมการหน่วงเวลาที่เหมาะสมคือการทำให้แอปเข้าสู่โหมดสลีปในช่วงเวลานั้นดังนั้นจึงใช้พลังงานน้อยลง
Thomas Tempelmann

ฉันใช้งาน 10.10.5 และโซลูชันนี้ใช้ไม่ได้
เกร็ก

@ThomasTempelmann: ปัญหาเกิดขึ้นเมื่อมีการป้อนข้อมูลของผู้ใช้ หากคุณไม่คลิกหรือพิมพ์ในขณะที่สคริปต์กำลังทำงานอยู่ข้อผิดพลาดจะไม่ถูกเรียกใช้
Chris Page

โปรดทราบว่าวิธีการแก้ปัญหานี้ทำให้แอปพลิเคชันหยุดทำงานจริงในช่วงระยะเวลาการนอนหลับ delayประมวลผลอินพุตของผู้ใช้ขณะที่สคริปต์ถูกหยุดชั่วคราวดังนั้นคุณยังสามารถโต้ตอบกับเมนูและหน้าต่างได้
Chris Page

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 วินาที) ให้ลองตั้งเป็นเดลต้านั้น ว่าเราสามารถตอบสนองได้บ้าง แต่ก็ยังแม่นยำ ความสงสัยคือบางครั้งการหน่วงเวลาไม่ทำงานดังนั้นการทำซ้ำในขณะที่วนซ้ำจะทำให้เธรดถูกล็อกไว้ แต่ในสถานการณ์ความสำเร็จเราต้องการให้เดลต้าการหน่วงเวลาสั้นเพื่อให้กระบวนการยังคงถูกขัดจังหวะ


การย่อความล่าช้าที่ร้องขอไม่จำเป็นและทำให้สคริปต์ทำงานช้าลงและใช้ CPU มากขึ้นในขณะที่รอ เวอร์ชันของฉันโทรล่าช้าจนกว่าระยะเวลาที่ต้องการทั้งหมดจะผ่านไปทำให้delayสามารถเลื่อนได้มากเท่าที่จะทำได้ก่อนที่จะดำเนินการต่อ
Chris Page

โปรดทราบว่าตั้งแต่คำตอบนี้ถูกโพสต์ฉันอัปเดตรหัสของฉันที่จะใช้delay endTime - (current date)แทนdelay durationซึ่งทำให้แน่ใจได้ว่าหากdelay ไม่ถูกขัดจังหวะมันจะไม่หยุดสคริปต์นานกว่าเวลาที่ร้องขอเดิมซึ่งอาจเป็นสิ่งที่คุณพยายามทำ ที่อยู่ด้วยคำตอบนี้
Chris Page

0

ดังนั้นเพื่อให้ทุกอย่างเข้าด้วยกันฉันเชื่อว่า Chris หมายถึงสิ่งนี้:

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.