Waiting for application response

Hi scripters,

Is there a way to make a script wait for an action to finish in order to avoid jamming up the automation?

What I want to accomplish:
I downloaded a bunch of images from NASA’s image server http://img.pds.nasa.gov/ to experiment with making animations out of them.
The files come in the ˜Planetary Data System’ file format and need to be converted to JPG’s to be able to work with them.
Some batch converting applications like the beautiful XnConvert exist, but they have trouble opening all the files (I guess 20% of the images get skipped).
The small application NASAView gets almost every file opened and converted, but it doesn’t provide batch functionality.
Applescript to the rescue. I collected snippets of code and made a script that does the job. It works by calling System Events to click menu items and press keys in order to achieve an automation sequence. I’m planning to convert about 300.000 files. It’s not fast, but I can let the script run day and night on a dedicated machine that won’t be touched.

The Problem:
The script jams from time to time. After increasing the delays in between the commands, the script runs longer: in about a day and a half it converts around 8000 files, but eventually it gets stuck too. The error message I get is:

error "System Events got an error: Can't get menu bar 1 of process \"NASAView\". Invalid index." number -1719 from menu bar 1 of process "NASAView"

In the Applescript log window I can see that the commands are logged faster than I see them executed.
For example: four return presses are immediately logged (and probably executed), but the process of actually seeing the different pop up windows appear and disappear takes longer.
I’m assuming that some kind of buffer runs out of memory eventually, resulting in Finder, or NASAView not being able to keep up with the script.

The solution?
Instead of using delays, it would make more sense to wait for the actions like key presses, or menu clicks to finish before continuing the script.
So. not only sending a keypress to a certain application, but also waiting until the action of the result of the keypress is finished, so that the application is ready to receive new commands again

The code:
The script currently looks like this:

(*

NASAVIEW batch
01: open NASAView
02: in the finder: select a data folder, and show only .IMG files by searching for the file extention .IMG
03: do one (or a few) images manually in NASAView, until the desired output folder is remembered in NASAView save dialog box as a default location
04: start the script
05: come back after a few days to check on the result
 
*)

set finished to 0
set i to 1

repeat while finished = 0
	-- GET SELECTED FILE IN THE FINDER
	tell application "Finder"
		set selectedFile to the selection -- Get selected Finder item (path described in Applescript language)
		set filePathAsText to selectedFile as text -- path as text with colons
		set filePathAsPOSIX to POSIX path of filePathAsText -- path as text with slashes
		set the clipboard to filePathAsPOSIX
		set currentFileName to do shell script "basename '" & filePathAsPOSIX & "'" -- get the file name (from a POSIX path)
		set fileExtention to name extension of (selectedFile as alias) -- file extention ( from the Applescript variable)
	end tell
	
	-- CHECK IF THE FILE IS GOOD TO WORK WITH
	if fileExtention is not equal to "IMG" then
		tell application "System Events" to key code 125 -- 125 = arrow down
		log currentFileName & " is a wrong file, selecting the file below this one and trying again"
		delay 0.3
	end if
	
	tell application "NASAView" to activate
	tell application "System Events"
		tell process "NASAView"
			
			-- OPEN FILE
			tell menu bar 1 to click menu item "Open Object" of menu "File" -- open file
			delay 0.4
			tell application "System Events" to key code 5 using {shift down, command down} -- 5 = g -- open "go to" dialog box
			delay 0.4
			tell application "System Events" to key code 9 using command down -- 9 = v -- paste the file path
			delay 0.4
			tell application "System Events" to key code 36 -- 36 = return -- enter the file path
			delay 1
			repeat 4 times
				tell application "System Events" to key code 36 -- 36 = return -- press enter to open the file, and press enter 3 more times to accept various dialog boxes in NASAView
				delay 0.3
			end repeat
			delay 1
			
			-- SAVE FILE AS JPEG
			tell menu bar 1 to click menu item "Save JPEG AS" of menu "File"
			delay 1
			tell application "System Events" to key code 36 -- 36 = return
			delay 0.8
			
			-- CLOSE FILE
			tell menu bar 1 to click menu item "Close" of menu "File"
			
		end tell
	end tell
	log "ok: " & i & " - " & currentFileName -- log, just for log's sake
	set i to i + 1
	
	-- GO TO NEXT FILE
	tell application "Finder"
		activate
		delay 0.2
		tell application "System Events" to key code 125 -- 125 = arrow down -- select the file below the current one in the list
		delay 0.2
		
		-- DID WE REACH THE END OF THE FOLDER?
		tell application "Finder" -- get selected item in the finder
			set newFilepath to the selection as text
			set newFilepathPOSIX to POSIX path of newFilepath
			set newFileName to do shell script "basename '" & newFilepathPOSIX & "'" -- get the file name (from a POSIX path)
		end tell
		if (currentFileName is equal to newFileName) then -- if the new file has the same name as the previous one, we're at the last file in the folder
			display dialog "twice the same filename: we're done!"
			set finished to 1
		end if
	end tell
end repeat

Thanks,
Elias

Hello, just matter of curiosity,

(a) why are you using do shell script to extract the name of a file when the Finder to which you are already speaking is able to do the job with :
set theFileName to name of theFile
where theFile may be an alias or a file reference ?

(b) why are you using key code which rely upon numerical values which may differ given the keyboard layout when keystroke may do the same with every layouts ?

key code 5 using {shift down, command down} – 5 = g – open “go to” dialog box
may be replaced by
keystroke “g” using {shift down, command down}

 key code 9 using command down -- 9 = v -- paste the file path

may be replaced by
keystroke “v” using {shift down, command down}

  key code 36 -- 36 = return -- enter the file path

may be replaced by
keystroke return

Yvan KOENIG (VALLAURIS, France) samedi 25 octobre 2014 15:21:14

Hello.

See if you can convolute the line in your script that errs with the construct below, if you now get the -1719 error, it delays 20 seconds, before it tries again, If some other error occurs, then it cascades the error as I have written it, you may maybe want to delay, whatever error happens.

I hth and good luck. :slight_smile:

repeat
	try
		-- command that generates error here
		exit repeat
	on error e number n
		if n = -1719 then
			delay 20
		else
			error e number n
		end if
		
	end try
end repeat

Hi Yvan,

Thanks, good remarks!

(a)
I think I had trouble getting it to work.
Being lazy, I guess the shell script was the first working answer I found.
I got an error message when I tried:

set fileName to name of theFile -- get the file name (from a POSIX path)

But when I apply the same syntax as how I get the extension, it works!

set fileName to name of (theFile as alias) -- get the file name (from a POSIX path)

(b)
I got the habit of a previous project I did. I can’t remember exactly why, but I must have seen it in examples on the web.
It’s definitely more transparent to work with the actual characters!

updated code:

(*

NASAVIEW batch
01: open NASAView
02: in the finder: select a data folder, and show only .IMG files by searching for the file extention .IMG
03: do one (or a few) images manually in NASAView, until the desired output folder is remembered in NASAView save dialog box as a default location
04: start the script
05: come back after a few days to check on the result
 
*)

set finished to 0
set i to 1

repeat while finished = 0
	-- GET SELECTED FILE IN THE FINDER
	tell application "Finder"
		set selectedFile to the selection -- Get selected Finder item (path described in Applescript language)
		set filePathAsText to selectedFile as text -- path as text with colons
		set filePathAsPOSIX to POSIX path of filePathAsText -- path as text with slashes
		set the clipboard to filePathAsPOSIX
		set currentFileName to name of (selectedFile as alias) -- get the file name (from a POSIX path)
		set fileExtention to name extension of (selectedFile as alias) -- file extention ( from the Applescript variable)
	end tell
	
	-- CHECK IF THE FILE IS GOOD TO WORK WITH
	if fileExtention is not equal to "IMG" then
		tell application "System Events" to key code 125 -- 125 = arrow down
		log currentFileName & " is a wrong file, selecting the file below this one and trying again"
		delay 0.3
	end if
	
	tell application "NASAView" to activate
	tell application "System Events"
		tell process "NASAView"
			
			-- OPEN FILE
			tell menu bar 1 to click menu item "Open Object" of menu "File" -- open file
			delay 0.4
			tell application "System Events" to keystroke "g" using {shift down, command down} -- open "go to" dialog box
			delay 0.4
			tell application "System Events" to keystroke "v" using command down -- paste the file path
			delay 0.4
			tell application "System Events" to keystroke return -- enter the file path
			delay 1
			repeat 4 times
				tell application "System Events" to keystroke return -- press enter to open the file, and press enter 3 more times to accept various dialog boxes in NASAView
				delay 0.3
			end repeat
			delay 1
			
			-- SAVE FILE AS JPEG
			tell menu bar 1 to click menu item "Save JPEG AS" of menu "File"
			delay 1
			tell application "System Events" to keystroke return -- go save the file
			delay 0.8
			
			-- CLOSE FILE
			tell menu bar 1 to click menu item "Close" of menu "File"
			
		end tell
	end tell
	log "ok: " & i & " - " & currentFileName -- log, just for log's sake
	set i to i + 1
	
	-- GO TO NEXT FILE
	tell application "Finder"
		activate
		delay 0.2
		tell application "System Events" to key code 125 -- 125 = arrow down -- select the file below the current one in the list
		delay 0.2
		
		-- DID WE REACH THE END OF THE FOLDER?
		tell application "Finder" -- get selected item in the finder
			set newFilepath to the selection as text
			set newFilepathPOSIX to POSIX path of newFilepath
			set newFileName to name of (newFilepathPOSIX as alias) -- get the file name (from a POSIX path)
			
		end tell
		if (currentFileName is equal to newFileName) then -- if the new file has the same name as the previous one, we're at the last file in the folder
			display dialog "twice the same filename: we're done!"
			set finished to 1
		end if
	end tell
end repeat

Hi McUsrII,

I saw your contribution only after I posted the reply to Yvan.
Interesting safety net you’ve suggested.
I’m going to try it out tomorrow!

I’m concluding that waiting for an application’s response is not possible or impractically hard.

Thanks so far Yvan and McUsrll!

Catching the error seems to work fine!
But it also seems that it doesn’t solve the problem.
After the error is catched, and the script paused for 20sec. only two other files are processed before the same error appears again. This seems to repeat itself.

It looks like the computer gets slower and slower over time. Like memory filling up or so…
If I restart the computer, the process goes smooth again, until we reach about a few thousand files, then these errors pop up again.

What could this be?
Is there a way to refresh the computer from time to time?
Doing batches of about 8000 files a time is not super useful since I have to process about 350000 of them…

Elias

I’ll be trying to purge the memory when an error occurred:

do shell script "purge" password "*****" with administrator privileges
delay 120

I hope that helps!

I don’t know the NASAView application, but it might be easier to use the Finder to open the images by passing them to
NASAView. The avoids a lot of tedious GUI scripting,

You have to change the string “gov.nasa.NASAView” to the proper bundle identifier of NASAView.app

And it’s probably not necessary to invoke ⇧⌘G in each iteration.

Untested


set imageFolder to choose folder
tell application "Finder"
	set imageFiles to every file of imageFolder whose name extension is "IMG"
end tell

activate application "NASAView"
repeat with aFile in imageFiles
	set hfsPath to aFile as text
	tell application "Finder" to open file hfsPath using application file id "gov.nasa.NASAView" -- replace the file id with the proper one
	
	tell application "System Events"
		tell process "NASAView"
			tell application "System Events" to key code 5 using {shift down, command down} -- 5 = g -- open "go to" dialog box
			delay 0.4
			tell application "System Events" to key code 9 using command down -- 9 = v -- paste the file path
			delay 0.4
			tell application "System Events" to key code 36 -- 36 = return -- enter the file path
			delay 1
			repeat 4 times
				tell application "System Events" to key code 36 -- 36 = return -- press enter to open the file, and press enter 3 more times to accept various dialog boxes in NASAView
				delay 0.3
			end repeat
			delay 1
			
			-- SAVE FILE AS JPEG
			tell menu bar 1 to click menu item "Save JPEG AS" of menu "File"
			delay 1
			tell application "System Events" to key code 36 -- 36 = return
			delay 0.8
			
			-- CLOSE FILE
			tell menu bar 1 to click menu item "Close" of menu "File"
			
		end tell
	end tell
	log "ok: " & i & " - " & (name of aFile) -- log, just for log's sake
	
	
end repeat


I recommend also to replace the delay lines with something more reliable
for example to wait until a specific window has opened


repeat until exists window "Save"
				delay 0.2
			end repeat


Hi StefanK,

interesting suggestions,
I’ll try them out right away!

Thanks!

Hello.

I had a look at the NasaView’s download page, they state that the application is old, and not tested for intel processors. If it is so, that Stefan’s suggestions, and fixes doesn’t work for you, then I suggest that you stop the script every 24 hours or so, quits the NasaView, System Events, and Finder, before you start up again. The only thing you loose by this, is some 10 minutes of processing time, which eventually will count for something.
Doing a quick back on the envelope calculation, you’ll have to have your script running in around 43.75 days anyways. Say you loose processing of 55 images during the 10 minutes, it will still only take like 8 hours more processing time in the end. :slight_smile: (The alternative may be to find a commandline tool that work.)

Hi McUsrII

It’s true, NasaView seems to be around for a while.
The idea to restart now and then sounds interesting, but do you think that purging the memory from time to time isn’t going to help too?
I’m afraid to loose track when I restart the computer. Or is there a way to remember variables even when applescript closes?

Shhh! Don’t discourage me with the processing time! :slight_smile:

StefanK, sadly your idea of opening a file with the finder doesn’t work. Even dragging a .IMG file to the NASAView icon in the dock doesn’t do a thing. Same story with the ‘open with’ contextual menu.
Thanks for the code to iterate through a list of files. I think I’m not going to use it though. It might sound real stupid, but when something goes wrong, I have to start all over, whereas now I just select the next item and continue processing the remaining items in the folder. But maybe switching between NASAView and the Finder so often is creating all the trouble!
I keep it in the back of my head if things keep getting jammed up.

The ‘Repeat until exist’ code is what I was looking for.
Great!
I found some nice variants as well.
I changed most of the delays into these procedures.

Elias

Hello.

Well, yes, NasaView has been around for a while, and I guess they never anticipated it was going to be scripted to batch convert 350000 images. :smiley:

As for keeping tack/track of which file was processed last: Stefan added a log statement, which you can use as a reference, when you stop the script. I think just quitting NasaView, is a good vantage point, this will purge the memory, no need to restart the whole computer, not for starters, anyway.

I let the script run overnight, when I came back I expected to see an error message, but instead, thanks to the ‘repeat until exist’ code, the script was patiently running it’s cycles. What I expected seems to be true: after a while the cycle time gets longer: starting at a good paced 3 seconds en ending (when I manually stopped it moents ago), after 6174 cycles at a sluggish 18 seconds.

Every 1000 files I did a memory purge, but it didn’t seem to have any influence on cycle speed.

I’ll go ahead and try restarting just NASAView to see if it increases speed.

Hello.

Even if it may seem feasible to adjust the delays, to be longer and longer during the cycle, and maybe convert say 100-300 images more than the stipulated 5.300 per 24h. However there is a risk in doing so: the delay maybe won’t be large enough at some times then, because tasks are executed without your control on the computer, regarding keeping the system healthy and other system tasks, these taks may stall your script, so it times out. So, it is best to keep the delays rather large for robustness, so you don’t loose a 24h period of processing time.

Running purge is pointless voodoo. It sounds like NASAView is leaking memory, and the only way you can deal with that is regularly quitting and restarting it.

Hi Shane,

it would sure be cool if applescript had some effective voodoo besides the pointless as well :slight_smile:
after just closing and opening NASAview, he script goes fast again, but quickly shows a pattern like so:

cycle number, cycle time
139, 3s
140, 11s
141, 4s
142, 11s
143, 3s
144, 11s
145, 3s
146, 12s
147, 3s
148, 11s

The save dialog seems to need a lot of time every even cycle number.
I don’t know why the wait time shows this pattern.
In the longer cycle times, the script always seems to hang on the save window.
It seems to wait until the filelist is loaded. From there on, things appear to go smoothly.
I’ll try again, by making the folder write only (drop box) so it doesn’t want to load all the files.

McUsrII, I try now to work with the ‘repeat until exist’ codeblocks, that renders the longer delays obsolete.
I do use some shorter delays on less important parts. This approach seems to work well.

Off to some more testing.
Thanks to you all for the help so far!!

After some tweaking and still adding delays to release some pressure, the script is now able to make runs that go about 4000 cycles or so, maintaining a cycle time of around 5 to 6 seconds.

Heading in the right direction, but the script still stalls after a (long-ish) while.

When I come back to the computer NASAView has crashed and the following Finder error is displayed:

Is there any other way to prevent the computer from running out of memory?

Here’s the code I’m using now, if it can be of any use:


(*

NASAVIEW batch
01: open NASAView
02: in the finder: select a data folder, and show only .IMG files by searching for the file extention .IMG
03: do one (or a few) images manually in NASAView, until the desired output folder is remembered in NASAView save dialog box as a default location
04: start the script
05: come back after a few days to check on the result
 
*)

set delayShort to 0.3 --0.2
set delayLong to 1.2

set finished to 0
set i to 1
set mgStart to 0

repeat while finished = 0
	-- GET SELECTED FILE IN THE FINDER
	tell application "Finder"
		set selectedFile to the selection -- Get selected Finder item (path described in Applescript language)
		set filePathAsText to selectedFile as text -- path as text with colons
		set filePathAsPOSIX to POSIX path of filePathAsText -- path as text with slashes
		set currentFileName to name of (selectedFile as alias) -- get the file name (from a POSIX path)
		set fileExtention to name extension of (selectedFile as alias) -- file extention ( from the Applescript variable)
	end tell
	
	-- CHECK IF THE FILE IS GOOD TO WORK WITH
	if fileExtention is not equal to "IMG" then
		tell application "System Events" to key code 125 -- 125 = arrow down
		log currentFileName & " is a wrong file, selecting the file below this one and trying again"
		delay delayShort
	end if
	
	tell application "NASAView" to activate
	tell application "System Events"
		tell process "NASAView"
			
			-- OPEN FILE
			-- click menu item 'Open Object'
			repeat -- wrapper to catch your breath when error happens
				try
					tell menu bar 1 to click menu item "Open Object" of menu "File" -- open file
					exit repeat
				on error errorString number errorNumber
					if errorNumber = -1719 then
						log "error: " & errorNumber
						delay 20
					end if
				end try
			end repeat
			
			-- wait until the file I/O window is open
			repeat until exists window "Open"
			end repeat
			
			-- open 'Go to' text field
			tell application "System Events" to keystroke "g" using {shift down, command down}
			
			-- wait for text field to appear. If so, paste path
			tell text field 1 of sheet 1 of window "Open"
				repeat until (it exists)
				end repeat
				set value to filePathAsPOSIX
			end tell
			
			-- confirm the input
			tell application "System Events" to keystroke return
			
			-- wait for the text field sheet to disappear
			tell text field 1 of sheet 1 of window "Open"
				repeat until not (it exists)
				end repeat
			end tell
			
			-- open the file
			tell application "System Events" to keystroke return
			
			-- wait until the file I/O window is closed
			repeat until not (exists window "Open")
			end repeat
			
			-- wait until the dialog window with a YES button is opened
			tell button "Yes" of window 1
				repeat until (it exists)
				end repeat
			end tell
			--log "dialog window opened"
			
			-- open file
			tell application "System Events" to keystroke return
			
			-- wait until the dialog window with a YES button is closed
			tell button "Yes" of window 1
				repeat until not (it exists)
				end repeat
			end tell
			--log "dialog window closed"
			
			-- Press the enter key a few times for some aditional dialog windows that pop up sometimes
			repeat 3 times
				tell application "System Events" to keystroke return
			end repeat
			
			repeat until exists (window 1 whose name begins with "NASAView")
			end repeat
			--log "image opened"
			
			-- wait a little
			delay delayLong
			
			-- SAVE FILE AS JPEG
			repeat -- wrapper to catch your breath when error happens
				try
					tell menu bar 1 to click menu item "Save Gif As" of menu "File"
					exit repeat
				on error errorString number errorNumber
					if errorNumber = -1719 then
						log "error: " & errorNumber
						delay 20
					end if
				end try
			end repeat
			
			repeat until exists window "Save"
			end repeat
			--log "Save window opened"
			
			tell application "System Events" to keystroke return
			
			-- wait until the save dialog box is closed
			repeat until not (exists window "Save")
			end repeat
			--log "Save window closed"
			
			-- CLOSE FILE
			repeat -- wrapper to catch your breath when error happens
				try
					tell menu bar 1 to click menu item "Close" of menu "File"
					exit repeat
				on error errorString number errorNumber
					if errorNumber = -1719 then
						log "error: " & errorNumber
						delay 20
						(* if other errors appear: cascade further down with the other numbers
					else
						error errorString number errorNumber
						*)
					end if
				end try
			end repeat
			
			-- make sure the image is closed
			repeat until not (exists (window 1 whose name begins with "NASAView"))
			end repeat
			--log "image closed"
		end tell
	end tell
	
	-- log current cycle, filename and cycle time
	set mgStop to current date
	log i & currentFileName & mgStop - mgStart
	delay delayLong -- just as a buffer
	set mgStart to current date
	
	-- GO TO NEXT FILE
	tell application "Finder"
		activate
		tell application "System Events" to key code 125 -- 125 = arrow down -- select the file below the current one in the list
		delay delayShort
		
		-- DID WE REACH THE END OF THE FOLDER?
		tell application "Finder" -- get selected item in the finder
			set newFile to the selection -- Get selected Finder item (path described in Applescript language)
			set newFilePathAsText to newFile as text -- path as text with colons
			set newFilepathPOSIX to POSIX path of newFilePathAsText -- path as text with slashes
			set newFileName to name of (newFile as alias) -- get the file name (from a POSIX path)
		end tell
		if (currentFileName is equal to newFileName) then -- if the new file has the same name as the previous one, we're at the last file in the folder
			display dialog "twice the same filename: we're done!"
			set finished to 1
		end if
	end tell
	delay delayLong
	
	set i to i + 1
	if i mod 1000 is 999 then
		log "-- maintenance: restarting NASAView"
		tell application "NASAView" to quit
		delay 5
		tell application "NASAView" to activate
		delay 10
	end if
end repeat

Hello.

Maybe
you could try to run that memory purge app of yours while NasaView isn’t running, and before you are out of memory? It is just a shot in the dark, but worth trying before you restart you machine.

Okay, I’ll try to implement that in a few days.

I forgot to mention that it’s applescript that’s sucking up all the memory.
It makes sense to restart applescript once in a while.
Food for research: Maybe I can fire a shell script that waits a while before opening and running the script again.

Thank you, McUsrII!

Hi,

Just looked at the download page. For Macintosh:

Doesn’t this mean that it was tested on Mountain Lion (Intel) for 32 bit?

gl,
kel