Simple Script

Greetings! My son’s “Curious George Reading and Phonics” (which appears Carbonized and OS X friendly) refuses to change screen resolution to 800x600 and back again on my PowerBook. So … AppleScript to the rescue! Sorta.

(* Must save as a Stay Open Application in Script Editor *)
property appname : "Reading and Phonics"
on run
	do shell script "~/bin/cscreen -x 800 -y 600"
	activate application appname
end run
on idle
	tell application "System Events"
		if (exists process appname) is false then
			do shell script "~/bin/cscreen -x 1440 -y 900"
			quit me
		end if
	end tell
	return 5
end idle

I’m using cscreen to change the resolution (see VersionTracker, et. al.). Here’s the thing. If I substitute “TextEdit” for “Reading and Phonics” - this works fine. If I leave it as-is, Reading and Phonics launches, and then when I exit it … the idle loop never reaches the “quit me” part. Actually I’m not sure what it reaches. I have to Force Quit the AppleScript app and manually change back the resolution.

Another interesting clue (?): When I run “Reading and Phonics” it starts ANOTHER process - also called “Reading and Phonics” - and the original process then quits soon afterward. Still, it’s a process with the same name, and even the Activity Monitor shows the process name as “Reading and Phonics” <!>.

Clues, anyone?

If you launch “Reading and Phonics”, what does this script return for the application name?

tell application "System Events" to get name of every application process whose visible is true

Also, the part about the process quiting and restarting is a stickler. Does it have the same PID# or does it change?

Here’s what I get:

{"iChat", "Safari", "Finder", "Script Editor", "Activity Monitor", "Reading and Phonics"}

As for PIDs, “Reading and Phonics” came up as PID 1447, then I saw another “Reading and Phonics” as PID 1448, followed by PID 1447 going away. :-

Would be great if I could sleuth out why the application doesn’t change the display properly in the first place. (To be continued when I call their support line - hahahahahahaha!)

Don’t know if these work for you. The first shell snippet tells you the PID of a particular app:

ps axc|awk “{if ($5==“Mail”) print $1}”|tr ‘n’ ’ ’

Replace Mail to the name of the application in question.

The second shell snippet tells you if a process of a particular PID is alive:

ps -p -o pid | tail -n 1 | grep -v PID

It returns nothing if the process is not there, otherwise it echos back the PID.

Then you need to have a loop to poll the presence of the app, say every 5 second or so.

Thanks! I appreciate that.

Now, this is kinda funny (?) 'cause all this time I was expressly trying to avoid writing anything in shell (save that cscreen bit - and even that I guess an OSAX could be written). The awk stuff you’re showing is what I’m used to writing, but I figured there had to be an easier way in AppleScript. Say I’m not mistaken! :?

I guess what I really want to understand is, why is “TextEdit” found as a process, but not the other one? Maybe it has to do with whitespace in the process name? Hmm …

Ahh - see, awk is going to use whitespace as a separator, so looking for “Script Editor” or even “Reading and Phonics” isn’t going to cut it unless you get creative with awk params (or if you can slice it by column position).

I wonder if that’s what AppleScript is doing, and it doesn’t work as advertised when there are spaces in the process name?

I found that all of the running applications have a “psn_” in them when listed using “ps” I wrote the following to get a list of all active app’s and their PID’s:

#!/bin/sh

script to parse out pid’s and application names

ps -awwx | grep -v grep | grep psn_ | awk '{
pid_num = $1
gsub (/^.//,“”,$0)
gsub (/-psn.
$/,“”,$0)
print pid_num," " $0

}’

Andy

Ooh, nice. I know, this thread is morphing (not complaining, just adding to it) but here’s something to get rid of those grep -v grep’s I know you’d love to ditch:

ps -awwx | grep [p]sn_ | awk …

So now we have psn_ to look for, and I see you’ve got this neat list of PIDs and process names. Ahh, why not - let’s try it …

Well, that didn’t work either.

But, rather, it did. It just didn’t work in context.

The problem doesn’t seem to be detecting the app/process, but rather that the idle callback doesn’t seem to get called-back if I activate “Reading and Phonics” for some reason. I added a few beeps up-front. If I activate “TextExit” - no problem. For “Reading and Phonics” it’s like the idle callback just gets canceled and the AppleScript app just sits there until I force quit it. No beeps.

… nowwww, why is idle getting silenced.

Wow, not that tough a topic for a first post, eh? Ouch, who knew. :shock:

Man, how did this thread get here? ;¬)
Anyhow, here it is without the grep…

ps -awwx | awk '/[p]sn_/

And you could do it without a shell script file…

ps cax -o pid,ucomm

But that returns vevery process.

I don’t have the “Learning and Phonics” app to experiement with, but just for the heck of it you might try…

if not (exists process appname) then

which is essentially the same as your line of code, so it should make no difference. Also you might try extending the “return 5” to return 30" to give the system time to relocate the process. --Stabbing in the dark –

I know, I know - really, I didn’t want to turn to anything shell (as handy as it can be, I realize). So back to the topic - if someone has an AppleScript angle to offer, I’m all ears. Especially since the shell suggestions presented here, handy as they are, are eclipsed by the idle loop going AWOL. :frowning:

The first incarnation used not with (exists process appname) but the time was still 5. I’ll kick that up to 30 and try the original again. Thanks!

OK - tried the switcheroo with using “not” - no dice. Tried increasing the timeout. Ditto on the no dice.

However, this time (using 5 seconds, 10 or even 30) I just let it run. I didn’t try to force quit it for a change. Eventually I got the same thing I usually get when I force quit it: A message box with “Apple Event Timed Out.”

I didn’t mention this before because I thought it was a consequence of my doing a force quit. So much for that assumption.

So … what Apple Event, pray tell …

Another stab, have you tried using the PID# instead of the app name as the variable, you could even try increasing it by 1 (e.g., PID = 1447 + 1) since you mentioned that it releases that PID and comes back as 1 higher

set x to do shell script "ps cax | awk '/Learning/{print $1}'"
x + 1

It really sounds as though the app itself is the problem, so you may not be able to get around this one ;¬(

One more stab, try using the “Finder” instead of “System Events” in your tell block.

What about moving some of the code outside of the System Events tell block:

property appname : "Reading and Phonics"

on run
	do shell script "~/bin/cscreen -x 800 -y 600"
	activate application appname
end run

on idle
	tell application "System Events" to set current_apps to name of processes
	if current_apps does not contain appname then
		try
			do shell script "~/bin/cscreen -x 1440 -y 900"
			quit me
		end try
	else
		return 10
	end if
end idle

Jon

First off, the PID number changing suggests that there’s some kind of launcher app at work here. [Btw, it may or may not have the same name (i.e. there could be an invisible character in the name, trailing spaces, etc.), so don’t just assume it is the same just because it looks the same.]

Well that’s a significant question, and when you can answer it, you may have solved the riddle to this problem.

Try this:

Note: I chose 35 in the delay arbitrarily; choose some number greater than the time it takes to switch PID’s. A factor of 1.5 to 2 would be a good choice.

Thanks for those suggestions! Finder was the first thing I was using, but then I saw someone write one with System Events and thought switching to that would help.

I like the PID increment idea, except I’m mildly paranoid that the one day he tries it, some other process will fork or start anew right in the middle and botch that up. Still, worth a shot!

Jon, thanks for pointing out that there are try blocks in AppleScript - fantastic. I tried your suggestion as well, but no luck. It seems like the idle block just isn’t getting called for some reason. I can put a display dialog in here every minute and it’s a no-show. OTOH, I like your page of AppleScripts and I’m going to learn from that! Maybe I’ll finally write something using AppleScript Studio. :slight_smile:

RainyDay, another good use of the try block. It just never seems to reach it in the first place. Now, as I understand it, when the run block finishes (is that the right terminology in this case, blocks?) it should call idle right away, and then whatever idle returns, it uses that as the delay before calling again (more or less). Maybe when CGR&P is called, that first idle call is never made or …

Could CGR&P be goofing around under the hood with Apple Events and messing up some kind of message queue? Perhaps it’s flat-out messing up the idle loop? (I’m calling their support line at 11. Then the real fun begins. I oughta transcribe it - heh-heh …)

More suspicious evidence. I had to reboot at one point. I almost never have to reboot. Some funny business in the Finder or somewhere else under the hood. Just weird behavior I’ve never seen before I started experimenting with this.

Are you saving this script as an application and then running it by double-clicking on it (not from within Script Editor)? Without doing this, the idle handler will never be called.

Jon

Yes, it’s saved as a stay-open app and then run outside of Script Editor.