I need the script to know the pid of its own osascript process. That is because it needs to pass its own pid on to another process later. There can be a variable number of processes called osascript running at the same time so, I need a way to be specific.
I had thought of this:
tell application "System Events"
set my_pid to unix id of my process
end tell
set result to this_pid
But, that failed with
Is there another way for a running process to get its own pid (when the name is ambiguous) ? Would using ps to find the most recent instance of osascript be a way ?
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"
use scripting additions
set theID to current application's NSRunningApplication's currentApplication()'s processIdentifier()
I spoke too soon. I get back “-1” instead of the process id. I put the ASOC into a try/on error block but, no error was triggered. Is the “-1” result an error ? If so, is there a way to get back the cause ? The process is named osascript. Is that a problem ?
In this case I’ve confirmed there is a pid. The pid relates to the osascript process not the script it runs. Perhaps that’s the issue.
I’ll find another way. Easiest (but cumbersome) would be to get the pid when calling the script, saving that in a temporary file and reading that file in the called script. That is:
set script_pid to do shell script "osascript" & script_file & " & echo $!"
Then, save script_pid in a file and add code to script_file to read it. Another way would be for script_file to load the calling script and get the value of a global script_pid. Also, can still get the unique pid by looking for the most recent osascript process which in my case will always be the one needed.
use framework "Foundation"
use framework "AppKit" -- for NSWorkspace
use scripting additions
on watchForAppLaunches()
set theNSWorkspace to current application's NSWorkspace's sharedWorkspace()
set theNSNotificationCenter to theNSWorkspace's notificationCenter()
theNSNotificationCenter's addObserver:me selector:"appWasActivated:" |name|:(current application's NSWorkspaceDidActivateApplicationNotification) object:(missing value)
end watchForAppLaunches
on appWasActivated:theNSNotification
set userInfo to theNSNotification's userInfo()
set theApp to userInfo's valueForKey:(current application's NSWorkspaceApplicationKey)
set theAppName to (theApp's localizedName()) as text
set theID to theApp's processIdentifier() as integer
display dialog (theAppName & " was launched with pid " & theID)
stopWatchingForAppLaunches()
end appWasActivated:
on stopWatchingForAppLaunches()
set theNSWorkspace to current application's NSWorkspace's sharedWorkspace()
set theNSNotificationCenter to theNSWorkspace's notificationCenter()
theNSNotificationCenter's removeObserver:me
end stopWatchingForAppLaunches
watchForAppLaunches()
Shane, many thanks again. I’ve afraid ASOC is beyond me at present. So, I’ve gone with just doing a pgrep -n osascript to get the most recent instance of my osascript calls. It’s a kludge but it works for my purpose.
set theID to current application's NSRunningApplication's currentApplication()'s processIdentifier()
could be modified to find the PID of a running process (it is a hardware driver that needs to be restarted) within a Sandbox environment, i.e. without using System Events unix syntax ?
Does anybody know? (maybe I should open a new post for this)
Thank you very much Robert. Yes that works with a script file, but I cannot get it do work with a driver.app? If you have any other idea, I would be grateful.
Assuming you know the process’s bundle ID, you can use this:
use AppleScript version "2.5" -- macOS 10.11 or later
use framework "Foundation"
use framework "AppKit"
use scripting additions
set bundleId to "com.apple.Safari" -- whatever
set thePid to ((current application's NSRunningApplication's runningApplicationsWithBundleIdentifier:bundleId)'s firstObject())'s processIdentifier()
Here is another way to get the Process ID by comparing the times the process started.
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
on run
local cc, sc, i, pid, mdate, udate
set mdate to (current date)
copy mdate to udate
set sc to paragraphs of (do shell script "ps -ecwwo pid,lstart,comm | grep osascript")
repeat with i in sc
set pid to (word 1 of i) as integer
set cc to words 3 thru -2 of i
set umonth to (offset of (item 1 of cc) in "XXJanFebMarAprMayJunJulAugSepOctNovDec") div 3
tell udate to set {its month, its day, its year, its hours, its minutes, its seconds} to {umonth, item 2 of cc, item 6 of cc, item 3 of cc, item 4 of cc, item 5 of cc}
if mdate = udate then exit repeat -- this is the correct pid
set pid to 0 -- resets if date-times don't match
end repeat
-- pid now has the process id of this osacript
end run
if there is any delay from when the script first gets the date/time after it is launched
then change the last if statement to something like
if mdate - udate < 2 then exit repeat -- you can change the number from 2 to whatever your delay might be
Another way is to use passed arguments to find the correct osascript if more than one osascript is running.
The below code is your script run from a “do shell script” command
Call the script ThreadTest.scpt
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
on run args
local cc, osalist, i, pid, aid
if class of args is list then -- arguments passed come in as a list
set aid to item 1 of args -- 1st item is the random number passed as argument
end if
set osalist to paragraphs of (do shell script "ps -ecwwo pid,comm,args | grep osascript")
set atid to text item delimiters -- save current text item delimiter
set text item delimiters to " "
repeat with i in osalist
set pid to (word 1 of i) as integer
if text item 3 of i is "osascript" then
set cc to (text items 3 thru -1 of i) -- arguments passed to script
if (item -1 of cc) is aid then exit repeat -- this one has the correct pid
end if
set pid to 0 -- resets if not osascript or correct script name
end repeat
set text item delimiters to atid -- resets text item delimiter back to what it was
-- pid now has the process id of this osacript
delay 25
end run
and here is the calling code that starts the osascript
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
local cpath, cid
set atid to text item delimiters
set text item delimiters to "/"
get (text items 1 thru -2 of POSIX path of (path to me))
set cpath to ((text items 1 thru -2 of POSIX path of (path to me)) & "ThreadTest.scpt") as text
set cid to random number from 11111 to 99999
do shell script "osascript '" & cpath & "' " & (cid as text) & " &>/dev/null & echo $!"
set text item delimiters to atid -- resets text item delimiter back to what it was
by passing the “cid” variable which contains a random number,
we are able to find ourself with the unix “ps” command and the arguments that were passed to it.
Thank you to all, I had to park that development for a week ago, as Catalina is creating challenges for one of my Applescript projects. But I will come back to it and then report, how it went.
Thank you already! Uwe
P.S. Now off to post another cry for help (In Catalina Xcode does not show me a Sandbox turn off/on capability and my code does not show the right behaviour colours - something got wrong upon transfer)
Just to update that all versions work for me. I had to go to the respective app and via Show Package Content - Content - info.plist find out the right bundle identifier and then used Shane’s version ultimately.