Find out how the AppleScript Studio app was launched?

Hey does anyone know if there is a way to detect the way an app was launched.

I have an application that is run as a Login Item and I would like it do something different when run as a Login Item to what it normally does if you double click it.

I’m really struggling on this one, and its the only piece missing before my project is finished!

Please heeeeeeeeeeelp! :slight_smile:

Thanks
Ryan

This doesn’t directly answer your question, but is there a way to detect how long the computer has been logged in? Would your app be possibly launched by the user as their first app? Could you see if the user has only been logged in for, say 1 second, and then you could assume (big assumption here) that the app was started at login, and it would most likely take the user more than 1 second to even start the app from the dock?

Yeah that would do it - bit of a bodge, but it would work!

I’ve done some digging about and have found that the Parent Process for my application is “Finder” if you run it by double clicking, and “WindowServer” if it is run as a Login Item.

So if anyone has some AppleScript that could get the current Parent Process name as text, I could then do a quick comparison to find out which way the app was started!

So close and yet so far, please can anyone help get me across the final hurdle??!

Thanks
Ryan

Hi Ryan,

After a bit of poking around… The UNIX command ps’ll help in this.

The handler below gets a list of the parent process ID of every process under the user. Filters by the original application name. Then finds the name of the process with the ID.

my getParentProcessID("Safari")

-- Handler to get parent process name of the process whose name is passed to it.
-- John Maisey -- [url=http://www.nhoj.co.uk]www.nhoj.co.uk[/url] -- 2nd April 2007
on getParentProcessID(myAppName)
	try
		set PPID to first word of (do shell script "ps -o ppid,command -xc | grep " & quoted form of myAppName)
		return last paragraph of (do shell script "ps -o command -xc -p " & PPID)
	on error theErr
		return theErr
	end try
end getParentProcessID

I’m sure there’s some way of piping the grep result back into the ps command, but this works.

Best wishes

John M

All of my applications have WindowServer as their parent, so I don’t think that’s reliable.

Thank John for getting it started; I would use this though:

on fetchParentProcess(someCommand)
	-- `someCommand` is the name of the process that you want information on
	do shell script "/bin/ps -xco pid,command -p \"`/bin/ps -xco ppid,command | /usr/bin/grep " & (quoted form of someCommand) & " `\" | /usr/bin/grep -o '[[:alnum:]]\\{1,\\}'"
	set parentProcess to paragraphs 3 thru -1 of result
	
	set ASTID to AppleScript's text item delimiters
	set AppleScript's text item delimiters to " "
	try
		set parentProcess to {item 1 of parentProcess, ((items 2 thru -1 of parentProcess) as Unicode text)}
	end try
	set AppleScript's text item delimiters to ASTID
	
	return parentProcess
	--> {parent pid, parent command}
end fetchParentProcess

fetchParentProcess("Safari")

This way, you can compare two exact values; Without making a list, you’d probably have to use contains (or something similar), which could cause problems (e.g. “Finder” vs. “PathFinder”).

Ahh yes, backticks. That’s what I was looking for. Much better version than mine Bruce :slight_smile:

I think you may have used ppid when you mean to use pid? (in the first instance in the do shell script line.) Otherwise you’re getting the process id of the parent, of the parent. (if you see what I mean)

All my applications show up as WindowServer as well.

Best wishes

John M

Thanks for catching that; I fixed it above. :slight_smile:

Hey there, thanks very much for the detailed reply, I have tried it in my application and I’m getting NSInternalScriptError after calling the ‘fetchParentProcess’ function.

I have run the exact same command in Terminal and it executes without returning any output, so I’m guessing thats where the problem lies :frowning:

Do you have any clue what could be wrong?

I’m running OS X Tiger if thats of any help?

Thanks
Ryan

EDIT If I remove the last grep I get the ID and Name for WIndow Server output when I try it in Terminal, so its something to do with that last grep.

EDIT 2 I bodged it together just to display the output from the result of that shell script in a dialog when you run my app, and you are indeed right - in both cases (double clicking in Finder, and launching through Login Items) the parent process was WindowServer.

Do you know of any other way of making an app do something slightly different when run as a Login Item - maybe by passing parameters to it or detecting some other state? I’ve no idea how to proceed now, this is the missing piece then the whole app is done :frowning:

Thanks
Ryan

There also appears to be ways to do this using carbon, but I’m sorry that I don’t have the time to get involved with it right now enough to write up a bit of cut & paste code for you. This page and this page at adc seem to be good starting points for looking into this sort of task. Some searching on google showed a good deal of people using the ‘GetProcessInformation’ carbon command to return info about your current process and to then get info about the parent process.

If I might step back a bit, I’m more curious about WHY you want to do this than I am about how to do it. It seems to me that all of the people trying to do it are running up against a lot of road blocks, and I’m guessing that it’s because it’s not something you should be doing… from either an interface guidelines or a logical standpoint. Why is it so important that your users have such a customized experience based on how the app launches? Perhaps the effect you’re going for can or should be achieved in another way? Typically, an app is an app, and it should do the same thing no matter how it starts up. The two scenarios I can thing of that are most common for changing that behaviour are a) when the user is holding down a key at startup, and b) when the user drops something on the app versus just clicking on it.

Perhaps if we knew why you want to change this behavior, we could offer you reasonable alternatives. The two options I can think of are these…

  1. Create a second “utility” app to handle your startup. If you have a set of features that only happens for login items, then I might consider that a second application. Put THAT in the startup items programmatically for the user as a preference in your main application. Even if all it does is launch in the background and then launch your app with certain parameters, at least it is not behaving in unexpected ways and the user has the opportunity to be made aware that that’s how your app works.

  2. Make whatever the difference in your two startup modes are a feature or a preference… not an automatic behavior. Once your app launches give them the option of deciding how the app behaves. A menu item or button could be used to change the mode manually. Or, you could use a splash screen as your primary gateway when the app launches, and ask the user if they want mode a or mode b.

Let us know your reasons for doing things against the grain, and perhaps we could find a more accomodating solution or better reasons why you shouldn’t even be doing it. Sometimes difficult tasks are good learning experiences, while others are merely bad practice.

j

Hey there thanks for your replies.

Let me give you an overview of the purpose of the application.

It is designed to allow novice users a nice simple method of automating network volume connections during log in.

The default way of dragging existing network drives into your Login Items has the following drawbacks:

  • It’s a little cumbersome to do for novice users.
  • When you log in, every network volume mounts and then immediately opens a window to itself, resulting in a very messy screen.

I have written an application which allows users to create their list of favourite network drives in an iTunes-esque table view, and then install the application into their login items by using a checkbox. When the application runs as a login item it should go through this list and connect the volumes, quitting when finished. If it is run normally by double clicking, it should show the settings window instead.

The reason I would prefer not to do this as too seperate apps is again for simplicity from the point of view of a user. With two seperate apps, I have to put lots of tests in to ensure that both apps know where one another is so that they can access the settings file which is stored in the application bundle, so that settings may be preserved if the application is copied to another computer.

Additionally, there are a lot of functions I don’t want to have to duplicate across two apps.

What I have ended up doing to solve this problem is have a bash script which is called from the login items, launch the program after creating a temporary file in /tmp. This bash script is stored within the application bundle as well, and gets around the problem of having two seperate AppleScript apps, but gives the same level of simplicity from the end-users point of view that I was after, with minimal complications behind the scene :slight_smile:

Happy days!

Thanks for the help everyone!

Couldn’t the login app be contained inside the main app?

Yeah I guess it could be, but that would again involve two executables to worry about, and it makes it more complex putting the second app within the first doesn’t it? I’m no expert but these opinions are the result of a lot of trial and error of things that would fix the problem, but not necessarily work in AppleScript - or at least I couldn’t get them to work anyway.

It’s all good though, I rolled out the first version to a select few people in the office, and so far they seem to like it!

Thanks for everyones help!
Ryan