Suddenly can't access clipboard in multiple scripts and on multiple computers? Properties aren't stored?

I have bunch of scripts that I execute everyday that download some data, process it into CSV and add it to the pasteboard (I then manually paste it into a Google Docs spreadsheet).

I do this everyday on two different computers and it has worked flawlessly for months, until two days ago. The scripts still finish as expected (I display a notification at the end with some statistics and that is completely normal) but the result is not inserted into the clipboard when I execute them from the Script Menu or using osascript from the command line. However, if I execute them using Script Editor, the result is added to the clipboard as expected.

And this happens on two computers. None of them have been updated (or even restarted lately, their uptime is 116 and 61 days respectively). I have feeling that these computers’ clipboard (sometimes) are synchronized, but I have never really examined that (might just be that Remote Desktop is connected), but it feels like something has happened that affected both machines’ clipboard and it seems logical that is has something to do with clipboard synchronization.

Except for the Script Menu’s and osascript’s problems with the clipboard, when I use the clipboard manually (and, as I mentioned above) or using Script Editor, it works as expected.

I have restarted the pboard process on both machines, to no avail.

Another odd thing I discovered when I tried to debug this problem: I save some properties in these script (such as a timestamp for when the last time it was executed) and display when I launch them. When I run these script from Script Menu or using osascript one value is displayed, but when I run them using Script Editor another value (or no value/empty) is displayed. The scripts are stored on a Google Drive and linked to the user script folder. Don’t know if that matters.

Any ideas?

How were you originally saving the properties?
Properties in scripts were no longer being saved since several OSes ago. Apple removed this capability due to security concerns since Catalina, I think.

Are you sure? Because it does indeed work (most of the time).

I do something like this:

property lastDate : missing value

at the top of the script and then

set lastDate to current date

at the end of the script. Next time I execute the script I do

display notification "Last date " & lastDate

which displays the expected value.

Personally, I feel that as the processing speed of Macs has increased, clipboard operations have become a process that needs to be performed with great caution.

When you set specified data to the clipboard with the set the clipboard command, you need to retrieve the contents of the clipboard again to check whether the set data is there.

If it’s not there, you can wait a suitable amount of time using the delay command (say, 0.01 seconds) and check in a loop.

It seems that using Cocoa’s functions is a more reliable way to update the contents of the clipboard (pasteboard), so I don’t use the set the clipboard command much these days.

That’s about it.

The main reason was that if your script is a application, since applications are digitally signed when saved, then they can’t save because it would cause the program to change and then then digital signature would fail. That is why you shouldn’t expect any of your scripts to save the properties and should instead prepare to save the properties out to a preference file at end of exciting, then read them back in when run.

2 Likes

Is there an OSAX or similar for that purpose? No need to reinvent the wheel.

Is there an OSAX or similar for that purpose? No need to reinvent the wheel.

No need. There are several scripts already on this site for saving and retrieving preferences.
One of them is a script library I wrote myself.

Do you have a link(s)?

3rd party OSAX had been discontnued since macOS 10.15.

Here is my library script…

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

on get_Prefs(pFile as string)
	local cfile, show_list, ptype
	set cfile to (path to preferences as text) & "ScriptPrefs:" & pFile
	try
		alias cfile
	on error
		--display alert "\"" & pFile & "\" Doesn't exist!" giving up after 10
		return false
	end try
	set ptype to read (cfile as alias) for 4 -- 8
	(* if (id of (text 5 thru 8 of ptype) as text) is in {"0040", "0009"} then
		set ptype to text 1 thru 4 of ptype
	else
		set ptype to "text"
	end if *)
	try
		if ptype = "reco" then
			set show_list to read (cfile as alias) as record from 0
		else if ptype = "list" then
			set show_list to read (cfile as alias) as list from 0
		else if ptype = "text" then
			set show_list to read (cfile as alias) as text from 0
		end if
	on error errMsg number errNum
		display alert errMsg giving up after 10
		set show_list to {}
	end try
	return show_list
end get_Prefs

on set_Prefs(pFile as string, pList)
	local cfile, flag
	set flag to false
	set cfile to (path to preferences as text)
	try
		alias (cfile & "ScriptPrefs:")
	on error
		try
			tell application "System Events"
				make new folder at folder cfile with properties {name:"ScriptPrefs"}
			end tell
		on error
			display alert "Error creating folder \"ScriptPrefs\" in Preferences." giving up after 10
			return false
		end try
	end try
	set cfile to cfile & "ScriptPrefs:" & pFile
	try
		set cfile to open for access cfile with write permission
	on error eStr number eNum
		display alert "Error opening file " & pFile giving up after 10
		return false
	end try
	try
		set eof cfile to 0
		if class of pList = record then
			write pList to cfile as record
		else if class of pList = list then
			write pList to cfile as list
		else if class of pList = text then
			write pList to cfile as text
		else
			write pList to cfile
		end if
	on error
		display alert "Error! Can't write to preference file…" giving up after 10
	end try
	close access cfile
	return true
end set_Prefs

you use it by calling set_prefs(“pref_file_name.dat”,myList) at the end of your script to save your properties and variables. The first parameter is a file name. It can be anything you want. I try to use .dat as the file extension but it also could be anything line .txt or .prefs. The second parameter is best to be a list of the data you want to save. It can also be a record or just plain text.

you would read it back in at the beginning of your script by using get_prefs(“pref_file_name.dat”)

Here is a sample script to save and get preferences…

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

property prop1 : missing value
property prop2 : missing value

local tmp
set tmp to get_prefs("testscriptprefs.dat") of script "Preferences"
if tmp = false then  -- prefs file not created yet, set properties to starting values
	set {prop1, prop2} to {100, 500}
else
	set {prop1, prop2} to tmp
end if

set prop1 to prop1 + 5
set prop2 to prop2 + 10
display alert "Property 1 = " & prop1 & return & "Property 2 = " & prop2 giving up after 5
set_prefs("testscriptprefs.dat", {prop1, prop2}) of script "Preferences"