How do I force exit from a script?

I am trying to create a simple script that loops forever, but exits whenever the user uses command -Q, or logs out. This is what i have so far:

repeat
– do shell script “ping -c 1 192.168.1.1”
delay 1
– ultimately this will just ping every 2 or 3 minutes
end repeat

on quit
exit repeat
continue quit
end quit

The ‘On Quit’ command is being trapped, I have put in a display dialog, which comes up whenever I press command-Q, but the script just keeps running. This is to keep a problematic network router connection open. Pinging the server periodically works - I have been using a terminal window to do that. But, what I would like is a small script app that can be loaded and left running, but that will quit when told to do so, or when I log out. The above script, saved as an app, both with and without the ‘Stay Open’ option, will not quit - even when i select Quit from the script’s file menu.

What I really want is a command that will force the script to stop running. Another post here suggested using ‘error number - 128’ but I put that in the on quit routine, and it still does not have any effect. I have tried all kinds of tricks with loop counters, but have had no success.

Perhaps I am going about this all wrong - I thought this would be simple - if anybody has another way to do this simple task, I would appreciate it!

Thanks,
Griffin

Bring the script to the foreground and press apple + dot. This should stop the script.

Thanks for the quick response! This allows me to stop the script when it is running. I don’t know why I didn’t try that - I was doing that when it was running under the Script Editor. At least now I do not have to use force-quit to exit the app.

But, I am still interested in getting the Command -Q option to work. If this script is running, and I log out/shutdown, it hangs up the Mac while it waits for the application to quit, then it cancels the logout/shutdown function, displays an error dialog that the program is not responding to the Quit command, and then I have to manually exit the app, then do the logout again. I would prefer for this app to function like a normal app, and respond to Command -Q, which I assume will also allow it to be quit by the system when logging out or shutting down.

Thanks again,
Griffin

The app won’t quit because it is busy with its own businesses. However, you can use this code:

global finish

set finish to false

repeat
	if finish then exit repeat
	delay 1
end repeat

on quit
	set finish to true
end quit

Or “kill” the app in the “quit” handler. Eg, this one:
http://macscripter.net/exchange/comments.php?id=P103_0_1_0_C

ALRIGHT! - now this works! Thank you!

Only problem is with the delay statement. If the script is executing the delay statement, that statement has to finish before it will exit the script.

Now, I planned on setting the delay to 5 minutes, so 99.9% of the time the script would be executing the delay atatement, which means up to a 5 minute delay in exiting the script, which will time out the logout process. But, I decided I can live with pinging the server every 10 seconds, and a 10 second wait is acceptable.

So, two things, if anybody is interested:

  1. IS there a way to get the command-Q/Logout to interrupt the delay statement? This is purely for curiousity’s sake, as my problem is solved, so don’t anybody lose any sleep over it, especially in light of #2:

  2. I figured out a much better way to set this up, and it involves not using Applescript at all, so it doesn’t really apply to this forum, but here it is: because all i really wanted was to ping the server regularly, I just set up a cron job to execute the ping command once a minute. Much better, less overhead, and it all runs in the background, and does not interfere with logging on or off - i set it up as a System cron job, so it will even execute if no one is logged on. If I was still thinking like a UNIX admin (been a few years) that would have sprung to mind first. I guess sometimes you have to think inside the box… :wink:

But I really am interested in AppleScript, and learning more about it, so this was an excellent learning experience, and i am glad i found this forum, and will likely be asking other questions when i start doing other stuff with AppleScript.

Again, thanks jj for the help, I learned a lot.

Griffin

Uh, nevermind!

Okay - i should have re-read jj’s post before posting my reply. The script at the link that jj supplies in his post DOES kill the script immediately, so that (curiousity) problem is answered as well.

Griffin

Wow, you have no idea how long I had to search the web and post on message boards before I stumbled upon the answer to my problem here. I’m brand new to using Applescript, so this was quite an achievment for me:) I took your script and played with it a bit to create this:

global x

set x to 1

repeat
set x to (x + 1)
beep x
delay x
if x = 10 then
exit repeat
end if
end repeat

on quit
set x to 9
end quit

My only problem is it still won’t quit on logout; you have to manually quit first. Any way to fix that?

Curious… :!:
It does work if you use apple + q, but not when invoked from the quit menu in the Dock (I assume it’s the same behaviour than trying to logout). I’ll ask in another list.

Well, I thought about it.
Applets (applescript applications) are not multithreaded. This means that they won’t answer your requests while they are busy. In this code, the applet is allways busy (setting x to y, delaying x, etc.). There is only two ways to accept external events (eg, quit):

  • The applet is idle (it is not working, but awaiting for successes, eg when you save the applet as stay-open, and it does only contain a ‘idle’ handler).
  • The applet is stopped manually (sends itself a ‘quit’ event, via apple+dot or via apple+Q). I think apple+Q is new in OS X, in OS 9 there was only apple+dot, and perhaps apple+shift+Q :?:
    So, the applet won’t pay attention to external requests (from the Dock, from a logout action, etc.).
    The workaround is using a “idle” handler, and saving the application as stay-open. This code will do the same than the “repeat” loop, but you will use a “idle” instead of a “delay”, and this will allow the app to accept external requests.
global x

set x to 1

on idle
	set x to x + 1
	beep x
	return x --> loop every x seconds
end idle

→ remember save as “stay-open”, so the “idle” handler is called. You don’t need handle the quit. It will simply quit when requested.