Call application by ID instead of by Name

Is it possible for Applescript to call an application by process ID or some unique identification other than by name? One of my apps can launch multiple instances of itself, and each instance has the same name as the first instance. In my script, I get the name of the current application, then process some stuff, then activate the application again to paste in some data.

The problem is, when the script activates the application again, if there are multiple instances running, it will activate the first instance that was launched, rather than the one that was current at the time the script was run. My guess is this is because it’s calling the app by name, and there are multiple apps running with the same name!

So, is there some way other than by name, that I can refer to an active application?

You can get the id of a process from “System Events”:

tell application "System Events" to set F to id of process "Finder"
-- then use it:
tell (process id F) to set P to path to desktop as alias

I think your guess is right too. The second instance may be listed after the first because it has a higher id.

Thanks, but I cannot get your script to compile. Runs into trouble here

. Says

Sorry, CJ;

The System Events tell block has to include the second tell. I tested that in my script, and screwed up getting it into my post. Oops. /adam

tell application "System Events"
	set F to id of process "Finder"
	-- then use it:
	tell (process id F) to set P to path to desktop as alias
end tell

I must ask why you’re launching multiple instances of your application in the first place. What task(s) are you trying to accomplish?

I had to run several instances of VLC in order to analyse DVD’s of surgical footage taken with several cameras in the same operation. The above commands will be most helpful in controlling these instances. Thanks!

The obvious question, PJ, is how do you start the second instance of VLC from an AppleScript?

Mikey-san, I’m running an app called ArchiCAD (architectural CAD software). The app only allows one document to be open at a time, however it allows you to open multiple documents by launching multiple instances of the app. However, the app is always named “ArchiCAD” so the Finder cannot tell which instance I am referring to.

The revised code worked, Adam, thanks. I am trying to get the id of the current, or frontmost, application, but this isn’t working. I was using the following code to get the name of the application, but it doesn’t work to get its id.

set real_name to name of (info for (path to frontmost application))

So I tried this approach, but it didn’t work, either.

set F to id of frontmost application

ArchiCAD does not allow you to specify a text box as being either all caps, lowercase, etc. So, to convert lowercase type into all caps, you’d have to re-type the whole text entry. I’m using an applescript to copy the text to the clipboard, then process the lowercase text to uppercase using a comparison string of text, copy the result back to the clipboard, then paste it back into ArchiCAD. It worked great until this new version allowed multiple instances of ArchiCAD (not possible before this latest release).

This script (built on a hint from Kai) will find the diplayed name / ID pairs for every running application that is not in the background. You can get the IDs from there.

set name_id_pairs to {}
tell application "System Events"
	set AP to application processes where it is not background only -- this from Kai
	repeat with anApp in AP
		set end of name_id_pairs to {displayed name, id} of anApp
	end repeat
end tell
name_id_pairs

or something like this:

--set name_id_pairs to {}
set iCal to {}
tell application "System Events"
	set AP to application processes where it is not background only
	repeat with anApp in AP
		if displayed name of anApp is "iCal.app" then set end of iCal to id of anApp
		--set end of name_id_pairs to {displayed name, id} of anApp
	end repeat
end tell
name_id_pairs

Adam,
It’s highly unsatisfactory, and proably quite sloppy, but the only way I could find to do it was this:

do shell script "/Applications/VLC.app/Contents/MacOS/VLC"

I saved this as an application on its own, because it always freezes, and I have to force-quit.
However, it does the job and opens a new instance of VLC.
Is there a better way?
PJ.

Comments on the second script above:

Normally, if you were searching a list for a single instance, you’d include an “exit repeat” in the test sequence when you found it - no need to test the rest. In this case I didn’t because you have two instances and they may not show up one after the other.

Got it :lol:

tell application "VLC" to launch
tell application "VLC_copy" to launch
tell application "System Events"
	set vlc to displayed name of every process whose name contains "VLC"
	set vID to id of every process whose name contains "VLC"
end tell
set vlcProc to {}
repeat with k from 1 to count vlc
	set end of vlcProc to {item k of vlc, item k of vID}
end repeat
vlcProc -- {{VLC.app, 64356353}, {VLC_copy.app, 64487425}}

Okay, so I am able to get the process id of the current application, but I am unable to use that process id to refer to the application! In the script below, for example, it works fine running out of Script Editor. If you highlight a word and run the script, you’ll see your selected word appear in the dialog box. However, if you save and run the script from, for example, Text Edit the clipboard remains empty!

It seems like the “tell process proc_id” line isn’t working. I’ve tried “tell application whose id is proc_id” but that doesn’t work, either. Any ideas?

tell application "System Events"
	set proc_id to id of application processes where it is frontmost
	tell process proc_id
		set the clipboard to ""
		delay 0.5
		keystroke "c" using command down
		delay 0.5
	end tell
	display dialog (the clipboard)
end tell

I’ve got this much working:

tell application "VLC" to launch
tell application "VLC_copy" to launch
tell application "System Events" to set vlc to {displayed name of every process whose name is "VLC", id of every process whose name contains "VLC"}


repeat with aNum in (item 2 of vlc)
	tell application "System Events"
		set frontmost of process id aNum to true
		delay 1
		set visible of process id aNum to false
		delay 1
	end tell
end repeat

and this works:

tell application "VLC_copy" to quit
tell application "VLC" to quit

More than one way to skin a cat:

property vlc_1 : "VLC"
property vlc_2 : "VLC_copy"

tell application vlc_1 to launch
tell application vlc_2 to launch
tell application "System Events" to set vlc to {displayed name of every process whose name is "VLC", id of every process whose name contains "VLC"}

-- way number 1
repeat with aNum in (item 2 of vlc)
	tell application "System Events" to set frontmost of process id aNum to true
end repeat

-- alternative approach
(*repeat with anID in item 2 of vlc
	tell application "System Events" to tell process id anID
		set frontmost to true
		tell window 1 to if exists then
			perform action "AXRaise" -- brings a window to the front.
		end if
	end tell
end repeat*)

Here’s the piece of script I’m working on. So far, I’'m still stuck trying to tell the application using its process id to do anything! The tell command using keystroke “c” should have copied the block of text I had selected to the clipboard, but when the display dialog (the clipboard) command comes up, the clipboard is always empty. I know that the process id of the current app is working from line 2, but I can’t figure out how to refer to that app using its id.

tell application "System Events"
	set the clipboard to ""
	set proc_id to id of application processes where it is frontmost
	--display dialog proc_id
	tell process id proc_id
		keystroke "c" using command down
		delay 1
	end tell
	set source_text to the clipboard as string
	set this_item to source_text
	set this_item to my change_case_of(the source_text, "upper")
	set the clipboard to this_item
	display dialog (the clipboard)
end tell

on change_case_of(this_text, this_case)
	if this_case is "lower" then
		set the comparison_string to "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
		set the source_string to "abcdefghijklmnopqrstuvwxyz"
	else
		set the comparison_string to "abcdefghijklmnopqrstuvwxyz"
		set the source_string to "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
	end if
	set the new_text to ""
	repeat with thisChar in this_text
		set x to the offset of thisChar in the comparison_string
		if x is not 0 then
			set the new_text to (the new_text & character x of the source_string) as string
		else
			set the new_text to (the new_text & thisChar) as string
		end if
	end repeat
	return the new_text
end change_case_of

I don’t know what else might be troubling you, but proc_id in your script is a list of one item, and you want an integer:

set proc_id to (id of application processes where it is frontmost) as integer

tell application "System Events"
	set proc to (id of processes where it is frontmost)
	class of proc --> list
end tell

display dialog proc_id fakes you out because it coerces the list to a string for display purposes (not in the script).