Xojo not getting the value returned by the AppleScript

Hi There

I use Xojo 2022r3.2 on a Mac mini M1. I am currently trying to port on MacOS a Xojo app developed for windows. My app uses Office automation to interact with Microsoft Word. I therefore need to replace the OLE commands by Applescripts.

I therefore created an Applescript to get some of the styles from a word document, putting the styles in a list and returning the list as text to my Xojo app. It works under the script editor, I can see the list returned by the script. The script has been dragged-dropped to the XOJO UI and appears in the list of scripts available for my app.

But the code in Xojo receives an empty result. No error, just the result Xojo gets is empty.

My script “listerstyles” is this:

on run
	tell application "Microsoft Word"
		set monmodel to make new document
		set maliste to {}
		set b to count of Word styles of monmodel
			repeat with a from 1 to b
			set nomitem to name local of Word style a of monmodel as text
			if nomitem contains "titre" or nomitem contains "heading" then
				set end of maliste to nomitem & ","
			end if
			end repeat
		close monmodel saving no
	end tell
return maliste as text
end run

My Xojo code is this:

dim malistemac() as string
dim applescriptresult as string 
applescriptresult = listerstyles
MessageBox(applescriptresult) 'this is for verification propose; this is supposed to display the items returned, but mess box piping up is empty
malistemac() = applescriptresult.Split(",")

In the Xojo debug window the “applescriptresult” variable appears empty (in fact there is nothing in “text” tab, and there are some hexa data in the left column of the binary tab),

Any idea why Xojo does not receive the value returned by the AppleScript?

Many thanks

Pierre

Did you drag the script into the left pane of the IDE ? Your code does not seem to call it.

Probably the plist for getting permissions to do the AppleScript is missing from the Xojo app.

Michel, yes the script is listed in the left panel.

Beatrix, I saw some posts on the “plist” topic but I did not yet figure out how to create it, what to put in it, and how to attach it to my app.

This will be my next task to continue to learn the MAC world, completely new to me.

Thank you

Pierre

You may want to verify that the applescript actually gets the proper value. This will display an applescript dialog showing maliste. If the dialog does not show in the IDE, try the same script in the script editor.

on run
	tell application "Microsoft Word"
		set monmodel to make new document
		set maliste to {}
		set b to count of Word styles of monmodel
			repeat with a from 1 to b
			set nomitem to name local of Word style a of monmodel as text
			if nomitem contains "titre" or nomitem contains "heading" then
				set end of maliste to nomitem & ","
			end if
			end repeat
		close monmodel saving no
	end tell
display alert maliste
return maliste as text
end run

Put this text into a file

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>NSAppleEventsUsageDescription</key>
  <string>Demo</string>
</dict>
</plist>

Name it info.plist. Drag it into the project. You should now get a dialog asking you if you want to allow the AppleScript.

6 Likes

Awesome! it works perfectly!

I will look into it closely to understand how this works.

Many thanks Beatrix!

Pierre

Thanks so much for this snippet Beatirx. I’ve been beating my head for days trying to work out why a perfectly functional Applescript won’t work in Ventura when called in the same way it has for many years. Is this documented somewhere?

Apple is slowly putting the clamp down on AppleScript for (perfectly valid) security reasons. Putting this bit of stuff into your app’s info.plist informs the system that it needs to use Apple Events (the underlying technology behind AppleScript). Without it, the OS silently drops your AppleScript requests and returns null. It’s not a great design.

When your app tries to run a script for the first time, the system will ask the user if it’s OK for the app to do this. If the user says yes, the system remembers this setting for the future, and you will see a listing for the app in System Preferences > Security & Privacy > Automation.

1 Like

Thanks for the explanation -I was wondering how Apps found their way into the Automation area. It seems Apple components are spared needing to do this as I could happily run scripts with simple dialogs etc without issue.

Yes; Apple is selfish, not surprising :wink:

One more observation. The Applescripts failed with no errors - despite having try blocks throughout. Makes it very hard to debug…

If the app isn’t authorized to send Apple Events – i.e., if the user says “no way” when the system asked them for permission - the AppleScript never even gets executed, so your try blocks do nothing.

You can ask AppleScript if it’s allowed to run:

'get permissions for new app
dim target as NSAppleEventDescriptorMBS = NSAppleEventDescriptorMBS.descriptorWithBundleIdentifier(BundleID)

// we ask for all apple events
PermissionsForApp = NSAppleScriptMBS.DeterminePermissionToAutomateTarget(target, "****", "****", true)
PermissionsDictionary.Value(BundleID) = PermissionsForApp

if PermissionsForApp = 0 or PermissionsForApp = -1 then
  'everything okay
  Return True
else
  'show the user what they need to do
end if

From my AppleScript handler “runAS” (Xojo + Alfred)

You can add a script in the Xojo Build:
Right click on “macOS” in “Build Settings”, then “Add to ‘Build settings’” - “Build Step” - “Script”.
In this script paste the code:

If (CurrentBuildTarget = 7) or (CurrentBuildTarget = 16) Then ' Mac OS 32bit ou Mac OS 64bit
  Dim TpTextA, TpTextB, TpTxtErr as String ' https://www.mbsplugins.de/archive/2019-03-31/Required_keys_for_infoplist_fi
  
  ' OpenFile(CurrentBuildLocation) ' "c:\projects\IDEScriptTest.xojo_binary_project")
  ' OpenFile(CurrentBuildLocationNative)
  ' OpenFile("/Volumes/MBtom-HD2/Tampon/TextBatchConv.app/Contents/Resources/fr.lproj/Localizable.strings") ' Ouvre dans l'IDE
  
  ' Mac for Test : TpTextA = CurrentBuildLocationNative + "/" + CurrentBuildAppName + "/Contents/Resources/fr.lproj/Localizable.strings" ' NativePath
  
  TpTextA = CurrentBuildLocation + "/" + CurrentBuildAppName ' + ".app"
  
  ' Print(ProjectShellPath)
  
  TpTxtErr = ""
  ' ####################
  TpTextB = DoShellCommand("/usr/bin/defaults write " + TpTextA + "/Contents/Info ""NSAppleEventsUsageDescription"" ""Modify folder window view, Add login item, Make alias, Select item.""")
  If not(TpTextB = "") Then
    If TpTxtErr = "" Then
      TpTxtErr = TpTextB
    Else
      TpTxtErr = TpTxtErr + EndOfLine + TpTextB
    End If
  End If
  ' ####################
  TpTextB = DoShellCommand("/usr/bin/defaults write " + TpTextA + "/Contents/Info ""NSContactsUsageDescription"" ""Read Contacts in your AddressBook.""")
  If not(TpTextB = "") Then
    If TpTxtErr = "" Then
      TpTxtErr = TpTextB
    Else
      TpTxtErr = TpTxtErr + EndOfLine + TpTextB
    End If
  End If
  ' ####################
  If not(TpTxtErr = "") Then Print(TpTxtErr)
End If

There are 2 Plist modifications between the 3 “####################”. The first one is to allow Applescript in your application, the 2nd is to allow it to access AddressBook.
I modify this script from what I copied here in the Xojo forum with the help of the members.