.app does not save property

Hi,
if I export the below script as application, then property is not saved. Anyone else notice this problem?
BR
Hallenstal

property tmp : "not done yet"

set tmp to text returned of (display dialog "current text is: \"" & tmp & "\"
change text to:" default answer "" buttons {"OK"})

Not sure what you mean by not saved.
Do you mean the tmp property is not getting set properly to ehatever was input in the dialog?
or do you mean that the tmp property is not getting saved to file when the script is closed after execution?

The latter is because Scripts can no longer save property values anymore due to security changes since Catalina, I believe. (or maybe Big Sur)

If you’re running a recent version of macOS in which properties are not saved, there are a number of alternatives discussed in:

A simple alternative not mentioned in the above thread is a text file:

set settingFile to ((path to desktop as text) & "Saved Value.txt") -- change to desired value
try
	set theSetting to paragraph 1 of (read file settingFile)
on error
	set theSetting to "not done yet"
end try
set theSetting to text returned of (display dialog "current text is: \"" & theSetting & "\"
change text to:" default answer "" buttons {"OK"})
do shell script "echo " & theSetting & " > " & quoted form of (POSIX path of settingFile)
1 Like

A bit more ambitious approach. One file sort of a “registry” for properties for any script.

--example of how to use the handlers
if defaultProperties() then
	set hello to "hello world"
	writeProperty("hello", hello)
end if
log readProperty("hello")
-- end example


on configPrty()
	set propertyFile to "~/.applescript_properties" --Where properties are stored
	tell application "System Events"
		set myPath to (path to me) as text
	end tell
	return {propertyFile, hash(myPath)}
end configPrty

on defaultProperties()
	tell application "System Events"
		set myPath to (path to me)
	end tell
	tell application "Finder"
		set theModDat to modification date of myPath as text
	end tell
	if theModDat = readProperty("modificationTime") then
		return false
	else
		writeProperty("modificationTime", theModDat)
		return true
	end if
end defaultProperties

on writeProperty(theProperty, theValue)
	set {propertyFile, tag} to configPrty()
	set theValue to gsub(theValue, "\\", "\\057")
	set theValue to gsub(theValue, "\"", "\\042")
	set theValue to gsub(theValue, "'", "\\47")
	set cmd to "export LC_CTYPE=\"UTF-8\"; awk 'BEGIN{
	tag=\"" & tag & "\"
	property=\"" & theProperty & "\"
	v=\"" & theValue & "\"
	ORS=RS=\"\\036\"
	OFS=FS=\"\\034\"
	}
	$1==tag && $2==property{
		print  tag, property,v
		f=1
		next
	}
	{
	print $0 
	}
	END{
	if(f==0)print tag, property,v
	 }' " & propertyFile & "> " & propertyFile
	do shell script cmd
end writeProperty

on readProperty(theProperty)
	set {propertyFile, tag} to configPrty()
	set cmd to "export LC_CTYPE=\"UTF-8\"; awk  'BEGIN{
	tag=\"" & tag & "\"
	property=\"" & theProperty & "\"
	RS=\"\\036\"
	FS=\"\\034\"
	}
	$1==tag && $2==property{
		printf(\"%s\\n\",$3)
		exit
	 }' " & propertyFile
	return (do shell script cmd)
end readProperty

on clearProperty()
	set {propertyFile, tag} to configPrty()
	set cmd to "export LC_CTYPE=\"UTF-8\"; awk 'BEGIN{
	tag=\"" & tag & "\"
	ORS=RS=\"\\036\"
	OFS=FS=\"\\034\"
	}
	$1==tag{
		next
	}
	{
	print $0 
	}' " & propertyFile & "> " & propertyFile
	
	do shell script cmd
end clearProperty

on hash(s)
	set cmd to "export LC_CTYPE=\"UTF-8\"; awk -v s=\"" & s & "\" 'BEGIN{
	for(n=0;n<256;n++)ord[sprintf(\"%c\",n)] = n
 	p = 104729;
 	mod = 1048576;
 	x = 0;
 	split(s,chars, \"\");
 	for (i=1;i<=length(s); i++)x=(x*p+ord[chars[i]]) % mod
 	printf(\"%05x\\n\", x)
	}'"
	return (do shell script cmd)
end hash
on gsub(theText, target, repl)
	set AppleScript's text item delimiters to target
	set thelist to every text item of theText
	set AppleScript's text item delimiters to repl
	set theText to thelist as text
	set AppleScript's text item delimiters to ""
	return theText
end gsub
´´´

FWIW, the following is an ASObjC solution that can be used to store values for multiple scripts in one property list file.

use framework "Foundation"
use scripting additions

-- Normally the read handler would be called near to top of the script
-- and the write handler would be called near the bottom of the script.
-- They are reversed here just to demonstrate their operation.
-- Values that can be saved include text, numbers, lists, and dates
-- ScriptOne and ScriptTwo are key names and can be changed as desired.

-- write a text value
set theValue to "some text"
writePlist("ScriptOne", theValue)

-- write a list value
set theValue to {"a", "b", "c"}
writePlist("ScriptTwo", theValue)

-- read the first value
set theSetting to readPlist("ScriptOne")
if theSetting is (missing value) then set theSetting to ""
theSetting as text --> "some text"

-- read the second value
set theSetting to readPlist("ScriptTwo")
if theSetting is (missing value) then set theSetting to {}
theSetting as list --> {"a", "b", "c"}

on readPlist(theKey)
	set theDefaults to current application's NSUserDefaults's alloc()'s initWithSuiteName:"com.peavine.Scripts"
	return theDefaults's objectForKey:theKey
end readPlist

on writePlist(theKey, theValue)
	set theDefaults to current application's NSUserDefaults's alloc()'s initWithSuiteName:"com.peavine.Scripts"
	theDefaults's setObject:theValue forKey:theKey
end writePlist

Shane’s PrefsStorageLib script library is always a good solution, and it can be found here.

1 Like

I’ve been using these simple script routines below to save multiple values in a prefs file as an AppleScript List. It can easily be modified to use a record instead.

on get_prefs(pFile as string) -- pfile is name of preference file
	local cfile, prefsList
	set cfile to (path to preferences as text) & pFile
	try
		set cfile to open for access cfile with write permission
	on error
		display alert "Error opening file " & pFile giving up after 10
		return false
	end try
	try
		set prefsList to read cfile from 1 as list
	on error
		display alert "File Empty!" giving up after 10
		write {} to cfile as list
		set prefsList to {}
	end try
	close access cfile
	return prefsList
end get_prefs

on set_prefs(pFile as string, pList as list) -- plist is a list of things you want to save
	local cfile
	set cfile to (path to preferences as text) & pFile
	try
		set cfile to open for access cfile with write permission
	on error
		display alert "Error opening file " & pFile giving up after 10
		return false
	end try
	try
		set eof cfile to 0
		write pList to cfile as list
	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