Property values not being globally available


(Jörgen Stahle) #1

The fact that property values cannot be not preserved between two times a code signed applet is run is obvious and easy to adapt to. But recently I have noticed a bigger problem: there is also a difference in scope for properties in scripts compiled with Script debugger versus Script Editor. And these differences are present even for non signed scripts.

I guess this is well known for you guys, and maybe it is a deliberate feature of SD, but I then would need som help – because it have made at least one applet with complicated code, made for server use, unusable with Mojave where code signing is in practice necessary. I’m quite sure it will break other applets of mine too.

I’m not sure what the exact scope limitations are for properties with SD, but the example script below demonstrates at least one of them: properties that are defined by the run handler are (under some circumstances?) not preserved for the idle handler – if compiled under Script Debugger.

I haven’t even noticed these differences until beginning to code sign my applets for server use: An applet that is edited in SD, but not being code signed, behaves as I expect them when start it from Finder. But when code signed with SD, the applet breaks.

If I run the same applet inside SD in idle mode it also breaks – even if the applet is NOT code signed. On the other hand, if the applet is exported and code signed from Script Editor (if it has included script libraries I have to move them from inside the bundle to my user library) – the script does NOT break.

So my conclusions are:

• There is an essential difference between SE and SD in how handle property values are handled. Specifically properties that are defined by the run handler and used by the idle handler.

• Non signed applets created with SD are somehow recompiled by MacOS to use the ”original” Applescript behavior. But when code signed, the applet preserves its ”SD-behaviour” in respect to differences concerning preservation of property values.

I my real case I have a complicated applet for server use, where the code is by far too large to store in one script. Therefore big parts of it is moved to script libraries, included in the application bundle, to be called from the main script. This have worked fine in production for years. But now I need to code sign this applet for use on a server with Mojave – and then it breaks.

At startup the main script stores the script libraries as properties. Then, at start in the run handler, redefines some of the script-library-properties’ own properties. In some cases those properties-in-script-library-properties are also redefined from time to time in the idle handler.

Below is a simplified example illustrate the principle. To reproduce the problem run it as a standalone applet and then from inside SD in idle mode. Or Code signe the applet fråm SD.

What I hope with this post:

• A description of how the handling of properties differs when compiled in SD compared tu usual Applecsript behavior (if these differences ar delibarate and if there is more to know besides my conclusions above)

• Some advice on alternative methods… if this is the way it is meant to be

Here is the code example. The same code example is also attached as a application bundle.
PropScopeDemo.zip (63.6 KB)

Main.scpt:

property L1 : script “Lib1”

property L2 : script “Lib2”

on run

set L1’s ySomeProperty to “~/Library/Logs/ThisApp/”

set L1’s ySomeOtherProperty to ( current date )

set L2’s L1 to L1 – passing the log functions stored in L1 to L2 (which also have a property named L1)

L1’s aHandler() – Works with SD

L2’s anotherHandler() – Works with SD

end run

on idle

set L1’s ySomeOtherProperty to ( current date ) – a property that is redefined every now and then

L1’s aHandler() – Partly fails with SD

L2’s anotherHandler() – Totally fails with SD

return 1

end idle

Lib1.scpt:

property ySomeProperty : missing value

property ySomeOtherProperty : missing value

on aHandler()

activate

set dateString to “” & ySomeOtherProperty

display alert ySomeProperty message dateString buttons {“Cancel”, “OK”} cancel button 1

end aHandler

Lib2.scpt:

property L1 : missing value

on anotherHandler()

L1’s aHandler()

end anotherHandler


errOSAInternalTableOverflow Error: tips on Using Script Libraries
(Mark Alldritt) #2

Unfortunately I’m not able to reproduce the issues you describe here.

I created your libraries and loaded your main script into SD. When I run the script, I get two dialogs displaying ~/Library/Logs/ThisApp/ and the current date as one would expect. When I use SD’s Script>Execute>Idle command to invoke your script’s on idle handler I see the same to dialogs displaying ~/Library/Logs/ThisApp/ and the current date as one would expect.

I saved the main script as an applet (unsigned) and ran that from the Finder. I see the on run handler’s first two dialogs displaying ~/Library/Logs/ThisApp/ and the current date as one would expect. A second later, the on idle handler runs and displays ~/Library/Logs/ThisApp/ and the current date as one would expect. This continues until I quit the applet.

I re-saved the main script, this time codesigned, and ran it from the Finder. The results were the same: two dialogs displaying ~/Library/Logs/ThisApp/ and the current date from the on run handler and then two dialogs from the on idle handler displaying ~/Library/Logs/ThisApp/ and the current date as one would expect.

When running a script within SD, you need to take care to ensure that the script is not recompiled in the interval between running the on run handler and the on idle handler. Recompiling will reset global properties to their initial state. Recompiles can happen when enabling/disabling debugging and when any type of edit is made. When testing a scenario like this, please ensure that you run the on run handler to establish the expected variable before testing the on idle handler.

When an script is running as an applet, SD is no longer involved (unless debugging is enabled). I can guarantee you that, within an applet, its the same Apple code running script regardless of which app (SD or SE) saves it.

Further, once an script is running in an applet, the state of global properties is preserved until the script quits. The issues of a script being codesigned or not only effect the initial state of global variables (preserved from the last run or not) when the script is launched.


I’ll try and clarify how all this works with a simple example.

Here is a script that displays an increasing count from an on idle handler:

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

property theCount : 0

on idle
	set theCount to theCount + 1
	display dialog "Count: " & theCount buttons "OK" default button "OK"
	return 1
end idle

Save this as an stay-open applet (not codesigned) and run it and you see a succession of dialogs displaying an increasing count. When you quit and re-launch this applet, you’ll see the count continue on from where it left off from the first run.

if you re-save the applet with codesigning, you’ll see that the count starts at 1 each time the applet is launched. This is be cause the state of global properties is not preserved in codesigned applets.

Now, I’ll make it a little more complex by introducing a library.

CountLib:

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

property theCount : 0

And the main script is changed to this:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
use counterLib : script "CounterLib" version "1.0"

on idle
	set counterLib's theCount to (counterLib's theCount) + 1
	display dialog "Count: " & counterLib's theCount buttons "OK" default button "OK"
	return 1
end idle

Save this as an stay-open applet (without codesigning) and run it and you see the same succession of dialogs displaying an increasing count. The initial count will always be 1 every time the applet is launched. This is because a fresh copy of CountLib is loaded by AppleScript’s use library statement each time the script runs and the initial value within that library is 0.

Within SD, if you use the Script>Execute>Idle command to invoke the on idle handler you should see the same dialog displaying the count. Initially the count will display as 1 and increase with successive runs. If you make an edit (just type a space at the end of the script), and run the on idle handler, the count will return to 1 and begin increasing again each time the on idle handler runs.

I hope this clears things up, at least a little.


I see you’ve gone to considerable trouble to provide formatted code examples using Markdown. Please use the forum’s code quoting syntax instead as this makes it much simpler for us to load your code into SD for testing. It deals with things like quote and apostrophe characters properly.

```
property L1 : missing value  

on anotherHandler()  
    L1's aHandler()  
end anotherHandler  
```

The above produces this result:

property L1 : missing value

on anotherHandler()
	L1's aHandler()
end anotherHandler

(Jörgen Stahle) #3

Thanks for your answer, Mark.
This is very, very strange. I was running tests for hours to be really sure before my I posted my topic. It is perfectly clear that the applet you made from my code behaves differently than for me when run from SD (yes, with Script > Execute > idle).
I haven’t enabled debugging at all when working with these test, btw. (I’m new to SD and haven’t really tried debug mode so much yet.) So there has been no toggling there.
Did you try to run the attached script that was compiled in my environment? The cited code is just copied from there.
Well, this is really a mystery, and I don’t know how to go from here…
Anyway, I am happy that what happens in my environment is not the way it should be. So the must be an explanation to my troubles somewhere…

What you describe in the second part of your answer I am completely aware of, the fact that “the state of global properties is preserved until the script quits” and “a script being codesigned or not only effect the initial state of global variables”. That was what I tried to say in my first sentence, but it really has nothing to do with the issue here. I was just thinking that maybe compiling I SD did something more with the properties.

Also, thanks you for the information on how to use the code quoting syntax.

Jörgen


(Jörgen Stahle) #4

This is how it behaves for me (don’t bother the timer):



(Mark Alldritt) #5

I’ve figured out the problem: SD’s Persistent Properties setting. When this setting is off (unchecked), SD restores all global properties to their compile-time state each time a script runs.

With this setting unchecked, SD will reset all properties each time you run your on idle handler. Try toggling this setting to on (checked) and repeat your tests.


(Jörgen Stahle) #6

Persistent properties was enabled. And when toggling back and forth the script behaves exactly the same way.

But – it seems system language is involved!

I was thinking about what might differ your environment, Mark, from mine. One thing is that for my user in the system, Swedish is chosen as the main language. I guess yours is English.

So, even though language felt unlikely to be a cause involved, I made a new user account with English as the main language. And – voila – there the test applet worked as it should! That is, it worked as it works for you, Mark. No errors and missing values.

So surprisingly enough, language seems somehow to be involved here. Maybe the problem have to do with localizations, swedish letters, number formats or date formats?

Anyway, my urgent concern is not the behavior of running applets from inside SD – but how the standalone server applet behave after code signing it.

Now, Swedish is also the language for the user account on a Mac Mini with Mojave where I test server solutions. Since the applet I have trouble with (the real one we run on servers) gets errors of the same kind as the demo applet encounter (that is, when running it in idle mode from inside SD with Swedish as user language) – make me suspect that the reason might be the same. To me it seems that the something-going-wrong is kept with the applet when saving it code signed from SD.

I will test the server applet with the system language changed to English (but that might have to wait until Wednesday, when I’m on my workplace next time).


(Jörgen Stahle) #7

I did the test today – and my suspicion was confirmed, @alldritt. The problems with the code signed server applet disappeared when I changed the main language to English.
As I wrote before, the errors, when running the server applet with Swedish language, was of the same kind as the test-applet generated when the idle-handler was run from within SD with Swedish language: Values that has been reassigned to properties by the run-handler is lost when called from the idle handler. (Propably values that are reassigned in one idle-round are also not preserved to the other idle-round).


(Jörgen Stahle) #8

I would be very happy for a comment on this, @alldritt.


(Mark Alldritt) #9

I’m not sure how to respond. Despite your observation, a change of language will not alter the way AppleScript code is executed. It will alter how text, dates, currency values, etc. are displayed, but it will not change how AppleScript operates.

There is something going on in your system which we have not uncovered that is causing the strange behaviour you are experiencing.

You can try adding log statements to all your handlers and then use the system console to see what is logging generated as your script runs. This may give some clues as to what is happening. It will certainly show us the sequence of events which may be helpful.


(Jörgen Stahle) #10

Thaks for your reply, @alldritt

Well, this is going on in TWO systems. One of them is a brand new mac mini with no special configuration (except installations of applications like Indesign) and with user accounts created from scratch.

On both machines I have on user account with Swedish as main language – were I get the very much alike problems with the applet and with SD. And one user account with English as main language – were the same problems are totally absent.

I can do what you suggest with log statements, when I’ve got the time.

It would also be very interesting if you could do a simple test: create a Swedish user account and there do the same test with SD as you did before.


#11

I don’t know if this is the correct test, but I switched to another account, added Swedish to the Preferred Languages list, and dragged Swedish to the top (above English) so that dialogs, etc., are in Swedish, and ran your sample code in SD. It produced no errors. Have I left out something important?


(Jörgen Stahle) #12

Thank you for doing this test, @emendelson
Just to make sure:
• Did you do the test on Mojave?
• Did you restart the mac after the switching of main language for that user? (Some language related stuff is not changed until you do.)
• Did you execute idle handler from within SD? That’s were the problem happens
Jörgen


(Mark Alldritt) #13

As I said in a previous reply, I was able to reproduce the problem you describe within SD when I turn off Script Debugger’s Persistent Properties setting.

However, I understood you to say that the problem happens outside SD as well. I cannot reproduce this.


#14

Before I saw Mark’s report, I tried running the Idle handler with Swedish on, and got the same error message that Jost reported. But now I can’t repeat the problem either with or without persistent properties enabled, in Swedish or English. So I’ll drop out of this discussion, rather than clutter it up with incomplete information.


(Jörgen Stahle) #15

I discovered that this problem – running the test applet from SD – only happens with Mojave.

  1. I couldn’t reproduce it om my workplace Macbook which runs High Sierra (with Swedish as main language).
    On my Mac Mojave at home it fails every time I try, consequently (also after computer restarts and so on). And, as I wrote before @alldritt, persistent properties is ON as you can see below. I have tested to toggle it off/on.
  2. Today I tried to run the code signed server applet – the one we use in real production, but up till now unsigned – on a machine with Sierra (10.12) and Swedish as main language. It worked perfect with no errors. This is the same applet that consequently generates property value errors in Mojave.

So the problem (I strongly believe it is one problem) seems to be related to MacOS 10.14.


(Shane Stanley) #16

FWIW, I can’t reproduce the issue here under 10.14 with the OS set to Svenska. But I’m a bit confused by some of your description. You refer to a signed applet, but your screen shot immediately above is from a non-signed applet.

To be clear, if you have a signed applet open in Script Debugger, Persistent Properties will be off, and there’s no way you can change that without turning off signing. That means the issue will occur in SD in this case, because you’re are calling run and idle separately without persisting properties, and that’s expected behavior.

if you do turn signing off and turn Persistent Properties on, you will still have to call the run handler first, before you run the idle handler – with Persistent Properties off, the properties weren’t being kept once the script had run.

If you want to test “real world” behavior for this case, you can modify your run handler like so:

on run
	set L1's ySomeProperty to "~/Library/Logs/ThisApp/"
	set L1's ySomeOtherProperty to (current date)
	set L2's L1 to L1 -- passing the log functions stored in L1 to L2 (wich also have a property named L1)
	L1's aHandler() -- Works with SD 
	L2's anotherHandler() -- Works with SD
	idle
end run

In this case run and idle will be called together, and you should not see the problem – property persistence is irrelevant because it’s all in memory.

As an applet, your code runs fine here, signed or not.


(Jörgen Stahle) #17

@ShaneStanley
My test script is unsigned because when I made it – to demonstrate the problems with my signed server applet – I got very much alike problems with the test applet before signing it.

Your explanation clarifies why I get the errors when testing from SD.

If I do execute > run beforeI do execute > idle with the test applet in SD with persistent properties enabled (not recompiling it in-between) the property values are saved from my run-step to my idle-step – right?
Maybe that explains why the tests give different results and have nothing to do with OS version or language. Maybe.

But my original issue is still unsolved: Why running the signed production flow applet, as standalone, gives this kind of errors in Mojave with Swedish language. Not in Mojave/English and not in Sierra/Swedish.
I think I have to do what @alldritt suggested: Log stuff to the console from that applet and get back with that.


(Shane Stanley) #18

Yes.

FWIW, I could not reproduce the issue here with your sample script. Have you tried it (as opposed to your production script)?


(Jörgen Stahle) #19

No, I can’t. I’m pretty sure I did get the errors when running the sample script as standalone applet, but since the errors I got from idle-executing it from within SD was similar I focused on the latter. Maybe I have changed something that made it work in standalone mode.
The problem is not so urgent anymore, since I discovered a possible workaround: Using English as system language on the server.
Still it’s frustrating to not now what is going on. So when I have the time I might arrange logging in the way the Mark suggested. I did not know that output from the log can be displayed in the console, though – and when I try I cant find it in any of the logs covered by Console.
The production script normally writes what it does and all errors it might encounter to a log file (using echo [string] >> [file]). But – since that writing is done from an included script library and dependent upon the property values that is afflected by the errors in question – all logging fails when the problem is present (i.e. when code signed in Mojave with Swedish language). So the errors is shown in dialogs instead.


(Jörgen Stahle) #20

This is very confusing.
I changed the main language back from English to Swedish for the active user on the machine where I test the production script (to give you examples of the error dialogs mentioned above).
Then suddenly the built in logging (echo >>) works.
That logging shows other errors that i can trace to a function that compare timestamps. And shutting off that function makes the whole script work again.
Those timestamps are derived from (current date) but then handled in a way that makes them independent of system language. Therefore one could suspect something in Mojave breaks the language independence.
However – if I just turn off code signing that function (and the whole script) works as it should again!
So:

  1. I couldn’t reproduce the original problem after the switch of languages Swedish > English > Swedish. Strange, but let’s forget that for the moment.
  2. The function involving timestamp comparison brakes when the script is code signed.

Below are the handlers the script uses to make timestamp strings into date objects, and vice versa. Using them the script can read/write timestamp strings and compare them, as dateobjects, independent of system language.

on getLocalIndependentDateObjectFromString(pDateString) -- Input format: YYYY-MM-DD hh.mm.ss or YYYY-MM-DD hh:mm:ss
	try
		set AppleScript's text item delimiters to space
		set {datePart, timePart} to text items of pDateString
		set AppleScript's text item delimiters to "-"
		set {theYear, theMonth, theDay} to text items of datePart
		set AppleScript's text item delimiters to {".", ":"}
		set {theHour, theMinute, theSecond} to text items of timePart
		set AppleScript's text item delimiters to ""
		set {indepDate, indepDate's day, indepDate's year, indepDate's month, indepDate's day, indepDate's hours, indepDate's minutes, indepDate's seconds} to {current date, 1, theYear, theMonth, theDay, theHour, theMinute, theSecond} -- jo, dag måste först definieras
		return indepDate
	on error errT
		error "getLocalIndependentDateObjectFromString: " & errT
	end try
end getLocalIndependentDateObjectFromString

on getLocalIndependentDateTimeStringFromDateObject(pDateObject)
	try
		set {yearInt, monthInt, dayInt, hoursInt, minuteInt, secondInt} to {year of pDateObject, (month of pDateObject) as number, day of pDateObject, hours of pDateObject, minutes of pDateObject, seconds of pDateObject}
		set theDateString to "" & yearInt & "-" & (my twoDigit(monthInt)) & "-" & (my twoDigit(dayInt)) & " " & (my twoDigit(hoursInt)) & "." & (my twoDigit(minuteInt)) & "." & (my twoDigit(secondInt))
		return theDateString
	on error errT
		error "getLocalIndependentDateTimeStringFromDateObject: " & errT
	end try
end getLocalIndependentDateTimeStringFromDateObject

on twoDigit(the_number)
	return (text -2 thru -1 of ((the_number + 100) as string))
end twoDigit