Slow AppleScript execution from within a FileMaker script

I have a FileMaker database with fields for first name, last name, email address, and many others. I want to get that information into the Contacts app. For years I did it with an AppleScript, which is called from a native FileMaker script, which is attached to a button in the database, and it took maybe one second to run. Since moving to more recent macOS versions the script takes forever. The odd thing is, the script is still super-fast when run from Script Debugger.

Here is the script.
use AppleScript version “2.4” – Yosemite (10.10) or later
use scripting additions

global firstname, lastname, emailaddress, yearofgraduation
tell application "FileMaker Pro"
	tell database "College Circuitry  all info"
		tell current record
			set firstname to cellValue of cell "Student First Name"
			set lastname to cellValue of cell "Student Last Name"
			set emailaddress to cellValue of cell "Student e-mail"

			set yearofgraduation to cellValue of cell "Year Of Graduation"
		end tell
	end tell
end tell
--
tell application "Contacts"
	activate
	-- VERY FAST TO HERE
	--
	-- STUDENT PART --
	set thegroups to name of every group as list
	set thegroupname to yearofgraduation & " students"
	--
	if thegroupname is not in thegroups then
		make new group with properties {name:thegroupname}
	end if
	--
	set x to make new person with properties {first name:firstname, last name:lastname}
	save
	tell x
		make new email at end of emails with properties {value:emailaddress}
	end tell
	set groupname to group thegroupname
	add x to groupname
	save
	--	
	display dialog firstname & " " & lastname & " has been added to the Contacts app."
end tell

I’ve tried to find where the slowdown is and I know for sure where it ISN’T:

It isn’t slow getting the info from FileMaker. if I do a “display dialog” with the info I’m grabbing, and a Return statement, it happens in a fraction of a second.

It isn’t slow launching Contacts.

Where is seems to be slow is actually doing the work in Contacts. There isn’t much to it (make new contact with properties, and then a save) but it takes minutes. Basically unusable.

I am guessing that this has something to do with newer security features in newer macOS versions. I think this problem began with 10.11 but it could have been 10.10.

If I run the script from the AppleScript script menu everything is fast, same as if I run it from Script Debugger. But it’s not as good as having the clickable button on the FileMaker database.

I’ve seen some other mentions of this sort of thing (FileMaker being slow to execute AppleScripts in new-ish macOS versions) but no solution. Anyone have an idea for me?

Rather than enumerating the names of every group, simply check to see whether the group with the given name exists:

set thegroupname to yearofgraduation & " students"
if not (the group thegroupname exists) then make ¬ 
        new group with properties {name:thegroupname} 

This won’t likely eradicate the issue unless you‘ve happened to have accumulated thousands of groups over the years. But it will reduce the number of messages sent between your script and the Contacts app, which could win you back a few milliseconds.

Going one step further, we can halve the number of times the contacts database gets written to (via save), remove the add command by creating the class objects within the appropriate container, and remove the need for the variable x. This could arguably increase performance by reducing the number of operations needed, but probably just in a theoretical sense rather than in any measurably practical way. But I doubt it’ll make things worse:

tell application "com.apple.AddressBook"
		set thegroupname to yearofgraduation & " students"
		tell the group named thegroupname to if (it exists) ¬
				or ((make new group at the end of my groups ¬
				with properties {name:thegroupname}) exists) ¬
				then tell (make new person with properties ¬
				{first name:firstname, last name:lastname}) ¬
				to make new email with properties ¬
				{value:emailadress}
		save
end tell

And who doesn’t love a one-liner ?

Thank you for this. Your one-liner is very impressive! However, this didn’t solve my “delay” problem. I have narrowed it down: when I run either your one-liner or my lots-of-lines from the Scripts menu, it’s lickety-split. About 3 seconds on a 2012 MacBook Pro. When I run either script from within FileMaker-- that is, I am running an AppleScript within a FileMaker script-- it takes over 60 seconds.

There’s a process called tccd that ramps up like crazy when the script is run from within FileMaker. I don’t see that happening when I run the script from the Scripts menu. Take a look at this screenshot of Activity Monitor, taken while the script is running from inside the FileMaker database:

The slow-down seems to be tied to this tccd process kicking in. I can work around it by saving the AppleScript as an application, and reducing the FileMaker script simply

tell application "Finder"
	open application file "myapp" of folder "Applications" of startup disk
end tell

This works, but it’s more trouble to maintain because I will have to put my “myapp” application onto every machine that runs the script, whereas doing it all within FileMaker’s “run AppleScript” script step means it’s self-contained.

So… I’ve solved it, and the script is more elegant thanks to you, but I’d rather do it with FileMaker, which knows how to run an AppleScript but triggers this tccd process when it tries to control the Contacts app.

Or:

launch application "myapp"

if you Google, it turns out tccd is a recurring and common problem since Mavericks. you could try revoking File Maker’s permission to access contacts and then granting permission anew.

Yes, of course I googled it, and also I found plenty of matching problems, no one had an answer. I did try revoking FileMaker’s permissions, but that didn’t work. The tccd thing seems to be something I’ll just have to work around.

It’s interesting that telling FileMaker to open an app, and having the app do the work, solves the problem. That seems to imply that getting FileMaker out of the way works. We already know that FileMaker is the problem since I can run the script from Script Debugger, Script Editor, or from the Scripts menu-- or just double-click the script saved as an app-- and it’s perfect. I haven’t figured out a way to get FileMaker out of the mix from within a FileMaker script. That’s where I’m stuck.

Regarding my convoluted method of launching an app from within a Filemaker script: when running an AppleScript within a FileMaker script you’re in a slightly different world. If I try ‘launch application “myapp”’ within a FileMaker script the app won’t be launched. So I do it the clumsy way. At least it works. There might be a better way but I haven’t found it.

Thanks for your help–

No problem. I have one more idea that will probably be as duff as my others. Have you seen if running your main script from inside another script circumvents the issue ? Having the AppleScript process spawned by a process that isn’t File Maker, even though it’s the grandparent, might be worth experimenting with.

If File Maker can trigger a shell script, then:

osascript <<-'poo'
    tell application "File Maker Pro"
            .
            .
    end tell

    tell application "Contacts"
            .
            .
    end tell
poo

or:

osascript "/path/to/external.applescript"

or by way of the shebang #!/usr/bin/osascript.

If it only triggers AppleScripts, you can try the load script and run script commands, the former requiring a path to a compiled script, and the latter able to execute script passed to as a string or a reference.

All the best.

Thanks for this. I was heading in this direction but didn’t know how to get there. I have it working by having FileMaker run a simple script that opens an AppleScript app that does what I want, with the downside being the external AppleScript app. (Previously the AppleScript was built into the FileMaker database’s script.) Loading an external script has the same problem so I don’t think there’s an advantage to loading a script. FileMaker doesn’t do shell scripts so that option is out too. (FileMaker does not store a compiled version of the AppleScripts that FileMaker runs via its own scripting system. Instead, it compiles the AppleScript code every single time that it runs, which of course slows things down a bit.)

Thanks again for the help and the idea about “getting outside of” FileMaker.

Here’s a thought. I use an applet running Myriad tables as a script palette. It runs outside of the app, but once it’s launched it stays open and all the commands execute without delay.

I have two versions, one that executes handlers within a single script and one that executes scripts saved in its folder.