The Omni Group
These forums are now read-only. Please visit our new forums to participate in discussion. A new account will be required to post in the new forums. For more info on the switch, see this post. Thank you!

Go Back   The Omni Group Forums > Developer > AppleScripting Omni Apps
FAQ Members List Calendar Search Today's Posts Mark Forums Read

Tell application WHAT? (a script for the perplexed) Thread Tools Search this Thread Display Modes

It shouldn't be, but the tell application block is a stumbling block, right at the start of drafting an applescript.

On my system, for example,
tell application "OmniFocus"
works, but
tell application "OmniOutliner"
fails, and so does
tell application "OmniGraffle"
Not only do you have to memorize some slightly arbitrary and inconsistent elaborations like:
tell application "OmniOutliner Professional"
tell application "OmniGraffle Professional 5"

but these references stop even very simple and general scripts from working across variants and versions of the same app (Professional versus vanilla, Ver. N versus Ver. N + 1)

Apple did introduce an improvement around OS X 10.5. Developers, they argued, are unlikely to change an application's 'bundle identifiers' and 'creator codes' across successive versions, whereas they do have a habit of changing its name, and so they introduced the format:
tell application id "com.omnigroup.OmniGrafflePro"
which looked promising because it didn't contain a version number.

And thus I personally generally switched to forms like:
tell application id "com.omnigroup.OmniFocus"
Which was fine, until I learned that the new AppStore versions have variant bundle names like com.omnigroup.OmniFocus.appstore and therefore choke on any applescript which starts with a line like the one above ...

So do we sigh and return to things like:
tell application "OmniGraffle Professional 5" ?
This makes sense if code is genuinely version-specific, but is frankly annoying in the numerous cases where the code for OmniOutliner and OmniOutliner Professional, or Omnigraffle vanilla, professional, or version whatever you like, would actually be identical ... (Two versions of OmniOutliner in the same office, professional and plain, and a need for a simple script which would run on both, for example).

This is why I am generally switching to a third application reference variant, which uses tell application id + creator code. Thus, for example:
tell application id "OOut"
for any version of OmniOutliner, and
tell application id "OGfl" for any version of OmniGraffle.
I have even adopted the reflex of
tell application id "sevs"
in place of
tell application "System Events"
All very well, but how do you learn and remember all these four-letter codes ?

Here is a script which will show you the four-letter creator codes (and the longer bundle identifiers) for all the applications currently running on your system. If you want, you can enter a search string, to filter down the list.

It will place a creator code (or bundle identifier) tell application block, for a selected application, in your clipboard.

(Ver .04 below should be compatible with LaunchBar and Keyboard Maestro. Tap space bar to pass a search string to it directly from LaunchBar).

-- Get creator codes and bundle identifiers for tell applications blocks
-- (for applications currently running
-- Ver .05 Compatible with LaunchBar - select script, tap space bar and enter string in Launchbar

property pTitle : "Tell application id ..."

property pDefaultSearch : "omni"

property pCodeCopy : "Copy creator code"
property pBundleCopy : "Copy bundle identifier"
property pNameCopy : "Copy app name"

-- System Events
on run
	tell application id "sevs"
		set strSearch to text returned of (display dialog "Enter part of application name:
(or leave blank to see all running applications)" default answer pDefaultSearch with title pTitle)
	end tell
end run

on handle_string(strSearch)
	tell application id "sevs"
		if (strSearch ≠ "") and (strSearch ≠ "*") then
			set {lstCode, lstBundle, lstFile} to {creator type, bundle identifier, file} of (application processes where name contains strSearch and bundle identifier is not missing value)
			set strPrompt to "Applications with \"" & strSearch & "\" in their name:"
			set {lstCode, lstBundle, lstName, lstFile} to {creator type, bundle identifier, name, file} of (application processes where bundle identifier is not missing value)
			set strPrompt to "All currently running applications:"
		end if
		repeat with i from 1 to length of lstCode
			set varFile to item i of lstFile
			if varFile ≠ missing value then
				set strName to (name of item i of lstFile)
				set strName to item i of lstName
			end if
			set item i of lstCode to item i of lstCode & "=" & item i of lstBundle & "=" & strName
		end repeat
		set my text item delimiters to linefeed
		set strApps to lstCode as string
		set lstApps to paragraphs of (do shell script "echo " & quoted form of strApps & " | sort -t '=' -k 3")
		if length of lstApps > 0 then
			set lstDefault to {first item of lstApps}
			display alert "No running apps have names matching " & strSearch
		end if
		set varChoice to choose from list lstApps with prompt strPrompt default items lstDefault with title pTitle
		if varChoice is false then return
		set my text item delimiters to "="
		set {strID, strBundle, strName} to text items 1 thru 3 of first item of varChoice
		set {blnCode, blnBundle, blnName} to {true, true, true}
		if strID ≠ "????" then
			set strCode to "tell application id \"" & strID & "\""
			set blnCode to false
			set strCode to strName & " has no creator code ..."
		end if
		if strBundle ≠ "missing value" then
			set strBundle to "tell application id \"" & strBundle & "\""
			set blnBundle to false
			set strBundle to strName & " has no bundle identifier"
		end if
		if strName ends with ".app" then
			set strName to text 1 thru -5 of strName
			set strAppName to "tell application \"" & strName & "\""
			set blnName to false
			set strAppName to ""
		end if
		set strChoice to "CREATOR CODE:    " & strCode & "

BUNDLE IDENTIFIER:    " & strBundle & "

APP NAME:    " & strAppName
		set lstBtns to {}
		if blnName then set end of lstBtns to pNameCopy
		if blnBundle then set end of lstBtns to pBundleCopy
		if blnCode then set end of lstBtns to pCodeCopy
		set lngButtons to length of lstBtns
		if lngButtons > 0 then
			set strClip to "-- " & strName & return
			set strBtn to (button returned of (display dialog strChoice buttons lstBtns default button lngButtons with title strName))
			if strBtn = pCodeCopy then
				set strClip to strClip & strCode
			else if strBtn = pBundleCopy then
				set strClip to strClip & strBundle
				set strClip to strAppName
			end if
			set the clipboard to strClip & return & return & "end tell"
			display alert strName & " is not a scriptable process"
		end if
		set my text item delimiters to space
	end tell
end handle_string

Last edited by RobTrew; 2011-05-28 at 12:19 AM.. Reason: Ver 0.3 - Will get its search string from LaunchBar
Hello, this may come a little bit late, but I have had the same problems with scripting for Quicksilver, which I believe is similar to Launchbar. I have some other fixes.

I have tasted my ways of doing stuff for everything, but a helpwindow on top.

I execute dialogs within the realm of SystemUIServer, because SystemUIserver is faster, since it knows both which screen, and space you are on, I think SystemEvents … and Finder are as smart, but not as fast.

		tell application "SystemUIServer"
				set failed to false
				display dialog theTime & " will be copied to the Clipboard!" with title procName with icon file clockIcon buttons {"Cancel", "Ok"} default button 2
				set the clipboard to theTime
			on error
				set failed to true
			end try
		end tell
(There is one detail to note here, that I don't process the errors from the dialog within the scope of SystemUiServer, I postpone that until I'm back into the scope of my script! )

However, since those scripts are in the middle of workflows, I'm pretty picky about specifying default buttons, and cancel buttons, so the script is fully operationable from the keyboard.

When the script is finished, I prefer My screen to be in the same state that I left it, with the same window fully active, without Me having to do anything.
I have this little hack with systemevents pressing down ctrl-F4 for Me, to do that, this will work with every app I think, since it is an OS-function, at least it works with Preview.

	tell application "System Events" to tell application process frontapp
			key down control
			key code 118
			key up control
		end tell
(There is one caveat with this, your screen is exactly as you left it, but! If your first action is to hit return, then you have to hit it twice, I consider this more a feature, than a bug. )
I actually put in another statement in the last block of code, clearing the keyboard buffer I believe, so now the script runs transparently in the workflow, as if it were never executed when it is done.

Here is the block calling system events to restore it all

		tell application "System Events" to tell application process frontapp
			key down control
			key code 118
			key up control
			key code 36
		end tell
And this, works under the assumption that volume keys and such are accessed by pressing down the fn -key! :)

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Similar Threads
Thread Thread Starter Forum Replies Last Post
setting project + context via script (modifying a DEVONthink script) bernd OmniFocus Extras 2 2012-09-08 01:10 PM
Application Switching voiceguy OmniFocus 1 for Mac 2 2012-09-01 08:18 PM
Application will not run on my iPhone mpretka OmniFocus for iPhone 15 2008-07-13 11:05 AM

All times are GMT -8. The time now is 02:21 PM.

Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2022, vBulletin Solutions, Inc.