Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

Ensure AppleScript App Quits

I have an AppleScript saved as a run only app which I call every hour from launchd.


Most of the time it works fine, but occasionally something causes the app not to quit when it's done its thing. This means that next time an error is thrown and the process does not run (so it fails until I force quit the app).


I have tried wrapping the whole script in a try...with timeout...end timeout...on error return...end try structure but that makes no difference.


The core of the script is a run shell script that calls a perl script which in turn gets data from a web site. I have tried nesting a try...on errror...end try around this that simply sets the content of the variable that should be populated from the script in the event that any error occurs.


The final part of the script is opening a [text] file and inserting a few lines at the top. Again I have tried wrapping this in a try...on error return...end try stricture.


None of these efforts seems to have any effect. However, I can't get the script to fail when I run it from the ApplScript Editor.


Would I be better to use osascript to call a script rather than the app, or am I doing something more fundamental wrong?

MacBook Pro, OS X Mountain Lion, MacBook Pro Late 2011 8GB RAM

Posted on Nov 30, 2012 4:20 AM

Reply
6 replies

Nov 30, 2012 10:08 AM in response to Arkouda

This is way too non-specific for me to venture anything but the most generic advice. You either need to show us the script or explain it more clearly.


The one question I do have is if this script is just a wrapper for a perl script, why not run the perl script directly from launchd and skip the applescript middleman?

Dec 2, 2012 3:44 PM in response to twtwtw

I'm sorry you find the question 'way too non-specific', I had tried to give all the detail I could.


I am not running the perl script directly as it's only a single part of the process: the data retrieval. I daresay I could write the whole thing in perl, but I am comfortable with manipulating the data; checking for condition(s) and writing to file with AppleScript.


Let me ask the question another way: If the previous execution of the app fails and the app is still running/hanging, could I wrap the entire process in another script (whatever language) to force it to quit before commencing the run?

Dec 2, 2012 4:17 PM in response to Arkouda

Maybe, depending... Of course, that's the last approach I'd usually try, because it's bound to be clunky.


Don't get me wrong. I'm not asking you for more detail to be annoying. I'm asking because without knowing what kind of hang/failure you're experiencing (or even what you're trying to do, for that matter) I'd just be shooting in the dark. You want a formulaic answer, but there isn't one, at least not at this level of abstraction.


Again with the generic advice: you do know that you can call a script app's handlers from other applescripts, right? So if you want to quit an app programatically just write a script that tells it to quit (or that calls a different handler that does cleanup before it quits). That won't work if the script is truly frozen - Applescript is not threaded, so it has to finish one script command before it can begin another - but if the script app has simply stopped (as sometimes happens) it should still respond to handler calls.


just out of curiosity, I'm assuming you saved this as a stay-open app (since part of the problem is that it stays open - lol); did you add an on idle handler? without an idle handler the script will just sit there waiting for something to call one of its other handlers. you need the idle handler if you want the app to check in periodically.

Dec 3, 2012 4:22 AM in response to twtwtw

I'm not trying to be coy either, but I don't see that posting the whole script is going to help particularly because the perl script uses WWW::Mechanize to get data from a website where I have to provide user credentials - hence, it will not be possible to run it without those credentials.


The expectation is that I will get approximately ten lines of data back (which I put into a local variable). I then use an offset check to determine whether a particular string is present. If it is present, I then go on to compose a message (using Messages) to send to myself.


Regardless of the content, I open a local text file and insert the web response at the beginning of the file (as an activity log). The file is then closed for access and that's it.


I have only once seen an error when I ran the script from the AS Editor and this seemed to indicate a problem with the site's availability - so when Mechanize couldn't find any identifiable data, it threw an error.


The app is not saved as stay open, but it does. All I can say for certain is that the log file does not get written to, so I suspect that the problem lies with the perl script. It is for that reason that I wrapped it in a try...with timeout structure. (My understanding of the timeout, is that if script execution fails to complete within the timeout an error will be thrown, so this is picked-up by the try...on error. That understanding may be wrong.)


So, after all that, here is the script [with a single hard-coded address obscured for privacy]:


try

set desktopPath to (path to desktop) as alias

set FlightCheckLog to (desktopPath as text) & "FlightCheckLog.txt"

set targetList to {"Sep-7", "Sep-8", "Sep-9", "Sep-10"}


tell application "Messages"

set theBuddy to buddy id "<OBSCURED>"

end tell

set messageSent to false


try

with timeout of 300 seconds

set theFlights to do shell script "~/Documents/perl/FilghtCheck.pl -x -c J -d 2013-09-07 ATH-LHR"

end timeout

on error

set theFlights to ""

end try


repeat with theDate in targetList


set theOffset to (offsetoftheDateintheFlights)

if theOffset is not 0 then

set theFlight to text (theOffset - 5) thru end of theFlights

set theReturn to (offsetofreturnintheFlight)

set theFlight to text 1 thru (theReturn - 1) of theFlight



tell application "Messages"


sendtheFlighttotheBuddy

set messageSent to true

end tell

end if


end repeat


try

set theFile to open for accessFlightCheckLog with write permission



get eoftheFile


if result > 0 then

set fileText to readtheFile


set eoftheFileto 0

else

set fileText to ""

end if



if messageSent then

write ((current date) & return & theFlights & return & "MESSAGE SENT" & return & return & fileText) as text to theFile

else

write ((current date) & return & theFlights & return & return & fileText) as text to theFile

end if



close accesstheFile

on error

return

end try


on error

return

end try

Dec 3, 2012 8:59 AM in response to Arkouda

A couple of style points that will make debugging easier. If you use try blocks, use the following pattern (which gives error feedback) and put the try blocks around the smallest units possible (which helps identify where the error is happening):


try


-- a command

on error errstr

tell application "System Events" to display dialog errstr

return

end try


keep in mind that a script app may not always report errors the same way as a running script, which is why I directed the DD to System Events.


That being said, the only places it seems to me this script could get stuck are with the shell script and open file commands. However, if the shell script were to hang it would not throw an error; the script would merely move on after 5 minutes, and you'd get an error that the variable theFlights has not been set. forget that try block and do it this way instead:


set theFlights to ""

with timeout of 300 seconds

set theFlights to do shell script "~/Documents/perl/FilghtCheck.pl -x -c J -d 2013-09-07 ATH-LHR"

end timeout

File access can fail if there's already an open pointer to the file - Applescript only allows one pointer, and for some reason throws an error rather than returning the open pointer. whenever I do file access during testing I use thin pattern, which tries to close open pointers and reopen the file:


try

set theFile to open for accessFlightCheckLog with write permission

on error


close accessFlightCheckLog

set theFile to open for accessFlightCheckLog with write permission

end try


So, get rid of that all-encompassing try blocks, make the changes I've suggested to the other try blocks and the file open line, and tell me what happens.

Dec 4, 2012 5:48 PM in response to Arkouda

Hello


The 'with timeout' statement does not apply to osax command.

Try the following code and see it returns true.


try
    with timeout of 1 second
        do shell script "sleep 3"
    end timeout
    return true
on error errs number errn
    return {errs, errn}
end try


I think your perl script is hanging.

Make sure it does exit or die properly.


Regards,

H

Ensure AppleScript App Quits

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple ID.