How to address an application that may not be installed

I am writing a universal script that talks to various apps, e.g. Safari and Chrome.

Now, some users do not have Chrome installed. While I can give them my script, and it works because I’m wrapping the code for Chrome in a try-catch block, the user will get annoying errors as soon as he’s trying to edit the script, forcing him to either install Chrome or remove the code talking to Chrome,

I wonder if there’s a way to edit a script in a way that it can be compiled even if the address application’s dictionary is not present.

Here’s the code I’m using currently, which attempts to read the browser’s currently shown URL:

		try
			tell front window of application id "com.google.Chrome" --  application "Google Chrome"
				set res to «class URL » of «class acTa»
			end tell
		end try

One idea was that the app I address will be frontmost. But there’s no “tell” that lets me just address the frontmost app, as far as I can find, and “tell front window of frontmost application” does not work, even though it compiles.

Here is a piece of code which I use quite often

		if isPages09 then
			-- Syntax accepted by Pages v.4.x
			save document 1 in file vraiCheminPDFfinal as "SLDocumentTypePDF"
			
		else
			-- raw format which may compile under Pages '09
			--«event Pgstexpo» document 1 given «class pfil»:file vraiCheminPDFfinal, «class exft»:«constant PgefPpdf» -- Keep this commented version because  Pages '09 refusile the export command available in Pages v.5.xe to comp
			-- export document 1 to file vraiCheminPDFfinal as PDF -- compile this way in Pages v5.
			«event Pgstexpo» document 1 given «class pfil»:file vraiCheminPDFfinal, «class exft»:«constant PgefPpdf»
		end if -- isPages09

I write the script with Pages v.5 running so I get the instruction [format]export document 1 to file vraiCheminPDFfinal as PDF – compile this way in Pages v5.[/format]

When the script is ready, I quit Pages v.5 (check in Activity Monitor that it’s not asleep.
Then I open the script with Pages '09 running so the export instruction appears in the raw format.
I save it in this status and export it as an application.
So most users users won’t be able to edit it and it will stay as is.
If one know how to reach the code in the package, I hope that my comments would be clear enough.

If you have an idea to enhance my comments please post it here.

Yvan KOENIG running El Capitan 10.11.6 in French (VALLAURIS, France) mardi 23 aout 2016 19:47:35

This may not be a good solution, because your intention seems to be increasing the ease with which a user edits a script, and this method will remove automatic formatting and compiler checks from most of the script… but I thought I’d post it anyway, because it does what you asked - it avoids the errors you get in Applescript when you don’t have an application installed.


set chromeInstalled to run script "
set hasChrome to true
try
	tell application \"Google Chrome\"
	end tell
on error
	set hasChrome to false
end try
return hasChrome"

if chromeInstalled is true then
	run script "
tell application \"Google Chrome\" to activate
"
end if

So it uses metascripting to put all “tell” statements inside a lower-level script, so they don’t hit compiler errors if the application doesn’t exist. And the first thing it does is check to see whether or not the application does exist, then it only directs commands at whatever applications they actually have.

If you want them to be able to edit the script with user-friendly formatting and compiler error checking, but not get warnings about applications that aren’t installed, then the only way I can think of right now is to get even more aggressive with your metascripting: provide the user with a script that they run, which will check what applications they have, then the script will generate a new script containing only the code relevant to the applications they have, and save that script on their computer. They can run and edit that seamlessly.

Another thought is, depending on why you want users to be able to edit the script, maybe instead of having them edit, you can provide the script with a config file it uses, and have them edit the config file.

Depends on why the end users are editing the script.

Oh yeah, and regarding this:

Use this:

tell application "System Events" to set appName to (the name of application processes whose frontmost is true) as text

tell application appName
	-- do stuff
end tell

Obviously, that alone won’t work, because the stuff that goes inside the “tell” has to use the Application Dictionary for whatever App “appName” is specifically.

But you can do this, and avoid any compiler checks for specific applications being installed:


	tell application "System Events" to set appName to (the name of application processes whose frontmost is true) as text


if appName is "Google Chrome" then
	tell application appName
		-- do stuff
	end tell
end if

if appName is "Safari" then
	tell application appName
		-- do stuff
	end tell
end if


Or have a separately compiled library script for each browser, with identically named handlers for equivalent functions. The main script would have to identify the browser being used and load the relevant library. Thereafter it would only need to tell the library to execute its versions of the various handlers.

Oh, that’s good thinking, Nigel.

I’m not very good at thinking library-oriented. Handy user-made libraries are relatively new to Applescript and haven’t fully permeated my solution set… which is a little ironic, because what I’m doing right now (when I’m not jumping back over to MacScripter) is editing an Applescript Library.

  • Tom.

Libraries with a capital “L” has only been available since Mavericks, but it’s been possible to use library scripts practically since AppleScript began, courtesy of the ‘load script’ command. In fact this older method would be more suitable for what I was suggesting, since it can load a script at run time and the main script can decide which library to load. With ‘use’, you’d have to load all the library scripts and just use the appropriate one. (Well. There’s a way round this, but ‘load script’ doesn’t need any tricks.)