An inability to use the AppleScript Foundation framework for scripts in DEVONthink Smart Rules has been discussed several times over the years: scripts with import statements such as this,
use AppleScript version "2.5"
use framework "Foundation"
use scripting additions
fail with obscure errors or simply don’t run at all when used in Smart Rules, but not when used outside of Smart Rules. Some examples of past postings in this forum where the topic came up include the following:
- Smart Rule fails only when triggered as a smart rule: (Can’t get name of «class DTcn» id 1296597 of «class DTkb» id 2.)
- Erratic behavior of Smart Rules and compiled AppleScripts
- Foundation framework performSmartRule error
- Script to sanitise file names - #10 by pete31
- Smart Rule scripts supporting inline AppleScriptObjC - #2 by cgrunenberg
The only solution has seemed to be to move the code into a separate script library, and then make the Smart Rule script import it, making sure that the code used in the Smart Rule portion does not itself import the Foundation framework. Some past postings where this was mentioned are:
- Foundation framework performSmartRule error - #5 by pete31
- Need help turning working script into smart rule capable version - #2 by cgrunenberg
- Script to sanitise file names - #2 by pete31
- Smart Rule scripts supporting inline AppleScriptObjC - #3 by pete31
- Automatically capture and annotate items (to use with Obsidian)
(My apologies if I missed some other relevant postings.) Recently, I stumbled headlong into this problem after having spent far too long writing some AppleScript code [1] that worked fine both in an external debugger and as a standalone program, and yet failed with a mysterious error -1708
when invoked from a Smart Rule. It was the first time I tried to use AppleScriptObjC with AppleScript, and in my naïveté, assumed it would just work. My balding head had too few hairs left to pull out in frustration, so with some degree of desperation, I spent even more time [2] searching for a way. And found one!
The basis of the approach is explained in a 2018 blog posting [3] by Shane Stanley (of Script Debugger fame) – I want to be clear it is not my invention. The pattern turns out to be simple. If you have a handler named HANDLERNAME where you need to use the Foundation framework, wrap it inside a script
object inside another handler, like this:
use AppleScript version "2.5"
use scripting additions
on HANDLERNAME(ARGUMENTS...)
script wrapperScript
property ca: a reference to current application
use framework "Foundation"
on HANDLERNAME(ARGUMENTS...)
... your code that uses AppleScriptObjC ...
return RESULT
end trim
end script
return wrapperScript's HANDLERNAME(ARGUMENTS...)
end HANDLERNAME
Here is an actual example of something I’m using successfully in a larger script invoked from a Smart Rule in DEVONthink version 3.9.4:
-- Remove leading & trailing whitespace from the text and return the result.
on trim(raw_text)
script wrapperScript
property ca: a reference to current application
use framework "Foundation"
on trim(raw_text)
set str to ca's NSString's stringWithString:raw_text
set whsp to ca's NSCharacterSet's whitespaceAndNewlineCharacterSet()
return (str's stringByTrimmingCharactersInSet:whsp) as text
end trim
end script
return wrapperScript's trim(raw_text)
end trim
The code above is not something for which you necessarily need the Foundation framework – you could surely implement it in plain AppleScript – but because it’s short, it’s useful as a example here. More important is the possibility offered by this general approach for using classes like NSURLRequest
, NSJSONSerialization
, etc, in your code. It does not necessarily represent an argument for using AppleScript instead of JavaScript and JXA, but if you need or want to use AppleScript, being able to access those classes can be a huge benefit.
Anyway, I wanted to share this, in the hopes that it will help other people.
[1] All the while, in the back of my mind, I could hear a certain person from this forum saying I should be using JavaScript. And it’s true; I really should have.
[2] This was plainly an example of the sunk cost fallacy at work.
[3] An archived copy is available in the Internet Archive’s Wayback Machine.