script abort, and logfile writing

Hello all,

These are very newbie questions that I’m about to ask, but I’m having a bit of a rough time transitioning from Perl to Applescript. :slight_smile:

  1. Is there a “die” equivalent in Applescript? In other words, if I’m at a point in the script where I want it to stop entirely, how do I do that? Right now I only seem to be do it via an increasingly complicated set of nested “if” loops. What I want to say is “if x happens, exit/quit/die/whatever”, and not just exit the particular loop I’m in.

  2. I’m having some trouble writing to an external file over the course of my script I can open the file fine and write to it once, but when I attempt to use the “write” command" in later parts of the script (such as within “if” loops"), I get the message “Finder got an error: File some object wasn’t open”. And if I try to reopen the file later, I get “Finder got an error: File permission error”. What I want to be able to do is open a file at the top of the script and then append to it little by little as my script goes along. Is this possible?

Thanks all!

Cheers,
John

My current log-writing handler:

-- debugging on?
property g_debug : true

--Log Entry Generation
-- With help from StephanK of MacScripter
-- http://bbs.applescript.net/viewtopic.php?pid=76607#p76607
--
on logMe(log_string, indent_level)
	if g_debug is true then --allows turning the debugger on and off so my logMe's can be left in final version
		set log_target to (g_home_folder_path & "Library:Logs:" & g_log_file_name) as text
		try
			set log_file_ref to open for access file log_target with write permission
			repeat indent_level times
				write tab to log_file_ref starting at eof
			end repeat
			write ((log_string as text) & return) to log_file_ref starting at eof
			close access log_file_ref
			return true
		on error
			try
				close access file log_target
			end try
			return false
		end try
	end if
end logMe

I use it like this:

my logMe("Some entry", 3)

I wanted the nicety of having indent levels to make my logs more readable when I am logging to death during troubleshooting.

Enjoy!

My log handler, logs Name, Time, and a Comment. Basicly the same.

my DoLog("File Error", "Not Closed")

on DoLog(TheName, TheComment)
	set the LogFile to ((path to desktop) as text) & "Script.log"
	try
		open for access file the LogFile with write permission
		set TimeStamp to do shell script "date -n '+%d/%m/%Y %H:%M:%S'"
		write ((TheName as string) & tab & TimeStamp & tab & (TheComment as string) & return) to file the LogFile starting at eof as string
		close access file the LogFile
		return true
	on error
		try
			close access file the LogFile
			return false
		end try
	end try
end DoLog

You open and close files, becuase if it errors you create whats called a leak. Program Script Debugger has a feature to help close leaks. Best is open, write, close, if error, close.

I do a tab delimited method so you can easily open in a database or back into AppleScript.

There is a log command, with start log, stop log. Which goes the the log console in Applescript Studio, Or in Script Debugger.

Just add the Log On/Off feature to mine, good idea.

So it now go like this

property LogStatus : true

my DoLog("File Error", "Not Closed")

on DoLog(TheName, TheComment)
	if LogStatus is true then
		set the LogFile to ((path to desktop) as text) & "Script.log"
		try
			open for access file the LogFile with write permission
			set TimeStamp to do shell script "date -n '+%d/%m/%Y %H:%M:%S'"
			write ((TheName as string) & tab & TimeStamp & tab & (TheComment as string) & return) to file the LogFile starting at eof as string
			close access file the LogFile
			return true
		on error
			try
				close access file the LogFile
				return false
			end try
		end try
	end if
end DoLog

With your question is there a kill feature. I dont know of a alsolutely anywhere kill. Expect pressing the Stop button or command period (I’ll try a GUI of that for fun, if you are running from non script editer, eg script menu, then you are out of luck). A return is a good method in root of your script. But if your are down a few levels in the stack, eg in a handler reutrn just exits the handler. You could return false, then ckeck for false and return again all the way out. Pain.

return
beep -- No beep as it exited

I hope someone else knows as a kill method would be useful

Have fun

Many thanks to Calvinfold and bevos for their posts. I was able to use Calvinfold’s subroutine (with some modifications) very successfully, so thanks for that! I probably should be interested on why I couldn’t get it to work my original way, but at this point I’m not. :slight_smile:

I’m still very interested in finding out the “kill/die” answer, because it seems impossible to believe that there’s absolutely no way to totally interrupt a script mid-run. The longer the script gets, the harder it would be to set constant “if true then start next ‘if’ loop” loops without making a mess out of the whole script. Maybe I’m missing something obvious. And Applescript will itself terminate if it encounters an error it considers fatal.

The usual way out is with a return in the run handler (top level of the script). Return with no arguments terminates the script’s execution.

try
– do something
on error e
– log the error
return – the script quits.
end try

or

set B to button returned of (display dialog blah, blah)
if B is “Oops” then return

The following statement cause to stop a running script in any location in the script.

error number -128

Excellent catch - even from a handler:

myHandle()
beep 3 -- never happens

on myHandle()
	error number -128
end myHandle

Thanks all! That “error number -128” trick is extremely useful.

I second that ‘error number -128’ is a quit silently (user cancel). After you pointed that out I check the AppleScript Language Guide and it there on page 209 (231 PDF page). I read that guide when I first learn and I can’t remember see that. Thanks again.

Of course you can report the cancel if you enclose in a try statement. Instead put your message in front of every cancel.

try
	test()
	beep
on error number errNum
	if errNum = -128 then display dialog "This cancelled just when I was having fun."
end try

on test()
	error number -128
end test

You can use this error number to navigate, like a goto, or get out of deep stacks, with a custom error (666 is not so evil, and not a normal error number) like this.

try
	test()
	beep
on error number errNum
	if errNum = 666 then display dialog "Error 666 now continue."
end try
display dialog "I got out of all those handlers Im free!"

on test()
	deeper()
	display dialog "Trapped"
end test

on deeper()
	display dialog "Can I get out of these handlers?"
	error number 666
end deeper

Comment out – error number 666 in deeper and see what happens.

So errors number passes down to the enclosed try statement so you can on error do something, if not nothing.

Therefore error -128 will not always get out. Example.

try
	test()
	beep
end try
display dialog "Didn't cancel"

on test()
	error number -128
end test

Since it inside a try statement, it didn’t cancel. error number are far better that exit or returns but not a absolute out.

So who know a absolute kill?