Connection is Invalid error (again)

I wish I could find some information on what this error means.

Since I have frequently run into problems with script applications I send other people not running on their machines unless it gets recompiled on their machines, I wanted to make a script that will do that. In other words, the target script I want them to have is included in a “master” script whose job it is to make an application of the target script on their machine.

That’s the big idea.

The first implementation of this, of course, is a really simple example in which the master script gets a file path, puts it in a property that is read by the target script, saves the target as an app, and then runs it. When I run the master script in Script Editor, it all works fine, but after the target runs successfully, I get the dreaded “Connection is invalid” error.

If I make the master script into an app and run it, the same thing happens except that instead of “Connection is invalid,” I get an “error -10873,” whatever that is. However, it seems pretty likely that it’s the same problem manifesting itself differently because the master is being run as an app rather than in Script Editor.

Anybody have any idea what’s going on?

Thanks in advance,

Larry the O

======================
property fileToOpen : “”

script fileOpenTest
tell application “Microsoft Word”
activate
open file fileToOpen
end tell
end script

on run
choose file with prompt “Choose an MS word file for this test.”
set fileToOpen to the result as string
set deskPath to path to desktop folder as string
set savePath to deskPath & “HeatherTest1.app”
store script fileOpenTest in file savePath
tell application savePath to run
end run

I am assuming that this is for people that do not know how to do the Save As… ???
any way, This seems to work.
Note that when you store the script you are not saving it as an app but rather an .scpt (AFAIK)
Also you could always zip the file up first, this has worked for me in the past.

property fileToOpen : ""

script fileOpenTest
	tell application "Microsoft Word"
		activate
		open file fileToOpen
	end tell
end script

on run
	choose file with prompt "Choose an MS word file for this test."
	set fileToOpen to the result as string
	set deskPath to path to desktop folder as string
	set savePath to deskPath & "HeatherTest1.app"
	
	save fileOpenTest as "application bundle" in file savePath without startup screen
	
	tell application "System Events"
		open savePath
	end tell
end run

As Mark said store script makes compiled scripts and not applications. If you wanted compiled scripts, you could add into the master script a constructor function that creates instances of script objects with properties. You could then run your saved compiled scripts with a master script (script runner) or from the scirpt menu. A simple script runner would look like this:

set f to choose file – the script
run script f

You could also pass parameters like the file to open to the compiled script. The script maker would look like this:

– creates an instance of script
on MakeScript(p)
script
property f : p
tell application “Microsoft Word”
activate
open f
end tell
end script
end MakeScript

on run
choose file with prompt “Choose an MS word file for this test.”
set fileToOpen to the result
set deskPath to path to desktop folder as string
set savePath to (deskPath & “HeatherTest2”) as file specification
set S to MakeScript(fileToOpen)
store script S in savePath
run script savePath
end run

gl,

This is really helpful.

First, to clarify, I’m making an application I want to send to people who know nothing of AppleScript and don’t want to. However, I have found that when I send applications to other people, they frequently won’t run. The fix is always to actually compile the script and save it as an app on the machine it will run on. (In this case, I sent it to two people, one with a PowerBook and one with an iBook, and it failed differently on each machine and ran fine after being compiled on each of the respective machines. So, the idea of this script is to compile it on each machine, and I’m just trying to save each person the extra step of double-clicking the resulting app to run it.

The Save As tip is the way I wanted to go immediately, but I couldn’t find the right syntax for expressing the format I wanted it saved in.

However, a question now comes up about the difference between compiled scripts and applications: is it possible to reset a property in an application? Can an application reset one of its own properties? Or do I have to use a compiled script to do that?

Thanks!

larry the o

A ‘property’ works the same in a Application as it does in a Compiled script. It holds onto the last value passed to it when the
Script or App runs.

Here also is the Description for ‘Save’ from the ‘Script Editor’ Library (Script Editor Suit)

save‚v : Save an object.
save reference : the object for the command
[as Unicode text] : The file type in which to save the data. Use one of the following strings: “script”, “application”, “script bundle”, “application bundle”, “text”.
[in alias] : The file in which to save the object.
[run only boolean] : Should the script be saved as Run-Only? If it is, you will not be able to edit the contents of the script again. The default is not to save as run only. (Applies to all script types except for “text”).
[startup screen boolean] : Show the startup screen? The default is not to show the startup screen. (Only applies to scripts saved as “application” or “application bundle”).
[stay open boolean] : Should the application remain open after it is launched? The default is not to stay open. (Only applies to scripts saved as “application” or “application bundle”).

I can’t get Save As to work at all. I tried copying and pasting your script, but it didn’t make the file it was supposed to make. So I tried playing around with the Save As command (like putting it inside a Tell application “Script Editor” block), but I couldn’t get it to work at all.

Very weird.

On my Tiger machine, but not the Jaguar one, a script stored with an “.app” name extension is indeed stored as an application. In that case, it can be run either by Mark’s suggestion of using System Events (or the FInder) to ‘open’ the file or Kel’s of using ‘run script’.

I don’t know if it’ll solve the problem of scripts not running on other people’s computers, as the script object code’s still compiled on the original machine, if I understand the process correctly. I suppose the solution depends on why the scripts don’t work elsewhere. Good luck, though.

That is weird.

I just found out what was happening to my tests.
The same as you, the save does not work?

What was happening was the system events part was opening the file already on the desktop from your script.
I should have guessed this, as I was not asked about replacing.

The Store works as Nigel says and saves as a Application Bundle if you put a .app extension.
This seems an odd way of doing things.

Well, the whole situation is weird. If all machines trying to run the script are relatively current and running a recent (i.e. latest or the one before) operating system, one would think it wouldn’t be necessary to compile the script on each target machine to get it to run. But that seems to be the case so far, so I’m trying to find a way to have it compile on each machine without user intervention (besides double-clicking to start things).

My hope is that if the code to compile the target code and save it as an app is simple enough, maybe it can run without problem on the different machines. But this is a very hinky and imprecise way to approach the whole problem. I am most definitely open to other suggestions on how to handle my problem. It is very inconvenient for me to have to physically go to each machine and recompile (and, possibly, troubleshoot).

Who’s got a better idea?

Thanks for all of your help.

Larry

One way to make sure the script is compiled on the target machine is to use text, Larry “ perhaps something like this:


set file_path to (path to desktop as Unicode text) & "HeatherTest1.app"

set fileToOpen to choose file of type "com.microsoft.word.doc" with prompt "Choose an MS word file for this test:" without invisibles

set script_text to "property fileToOpen : \"" & fileToOpen & "\"" & return & return & "tell application \"Microsoft Word\"" & return & "activate" & return & "open file fileToOpen" & return & "end tell"

tell application "Script Editor"
	save (make document with properties {text:script_text}) in file_path
	close front window
end tell

ignoring application responses
	run application file_path
end ignoring


However, I’m still tempted to reiterate Nigel’s comment “ and suggest taking a closer look at the reasons for the failures on the other machines. If you’re getting error messages, try posting them here; maybe someone can help to make sense of them…

Huh. That’s an interesting approach. So, you basically put all of the commands and such in a variable and tell Script Editor to save it with a file spec that uses a .app extension.

Troubleshooting the problems on the other machines is clearly the right way to go about it, but not practical in this case. First of all, programming is NOWHERE in my job spec to start with, so spending as much time as I already am is dicey, though tremendously useful to my employer. Second, the people I’m dealing with are not technically savvy (so much so that I had to explain to one of them how to do a screen capture so that I could see an error message she couldn’t describe), so troubleshooting requires considerable effort unless I can just sit down at their machines myself, which is also not practical.

In short, it’s a triage situation. One must always prioritize. The only reason I’m pursuing this far instead of just mucking through getting them to recompile on their machines and being done with it is in anticipation of future upgraded versions.

In any event, thanks tremendously for all of the help and suggestions.

kai got me thinking.

If your script is really long, all that escaping and formatting would most likely drive you nuts or put you off.

So why not put the script in between comment tags. (* *)

Inside the tags wrap the script with a second set of tags: Script_Start_Point and Script_End_point
Then use AppleScript’s delimiters to get the text in between.
The rest of the script saves the result as an App.

The only thing I need to figure out is how to make them have ‘stay open’

EDIT Doh ,figured that out. The make document opens a er… Document, so that means I can save it how I want :slight_smile:

Edit end**

Here is my example



on run
tell application "Script Editor"
		set the_name to name of document 1
		set the_contents to contents of document the_name
		set AppleScript's text item delimiters to "Script_Start_Point"
		set the_content to text item -1 of the_contents -- this works from bottom of text to first break point  "Script_Start_Point"
		set AppleScript's text item delimiters to "Script_End_Point"
		set script_text to text item 1 of the_content
		set AppleScript's text item delimiters to ""
	end tell
set file_path to (path to desktop as Unicode text) & "HeatherTest3.app"
tell application "Script Editor"
			make document with properties {text:script_text} 
			save document 1 as "application bundle" in file file_path with stay open without startup screen
			close window 1
end tell
	ignoring application responses
		run application file_path
	end ignoring
end run

-- paste script to be installed as an .app between the  "(* Script_Start_Point"  and  "Script_End_point  *)"
-- example below
(*

-- **** this is the first break point *** --> Script_Start_Point
display dialog "Tell me What to say" default answer " Hello World" buttons {"Cancel", "Say it"} default button 1
copy the result as list to {text_returned, button_pressed}
if button_pressed is "Say it" then
	say text_returned
end if

Script_End_point <--- **** this is the Script end  point *** 
*)

OK, I tried sending a script saved as an Application Bundle to two people. The first came back with the two problems, the same encountered before:

  1. She gets a dialog saying that Classic Support is required and is not present. She is running OS 10.4.9 and I am running 10.4.8 (and have been for months). I do have Classic Support on my machine, presumably because I had older versions of OS X on this machine before. Why is this script looking for Classic Support? (It’s a really long script, so I don’t think I can post the whole thing.)

  2. The script has a property for storing the path to the preferences file. The property is declared as “” and if the script finds the path to have that value, it generates a path using the user’s path to desktop:

if (prefsPath is “”) then --if the path to the Preferences file is not already stored, then derive it
–derive path to Preferences file
set deskPath to (path to desktop as string)
set AppleScript’s text item delimiters to “:”
repeat with x from 1 to ((count of text items in deskPath) - 2)
set prefsPath to prefsPath & text item x of deskPath & “:”
end repeat
set AppleScript’s text item delimiters to space
set prefsPath to prefsPath & “Library:Preferences:firstEdit Preferences.txt”
end if

When she tries to boot the app, it gives her a dialog that it can’t find the prefs file with the path used on MY machine. I presume that this value is somehow getting set into the property when I compile. I am contemplating two possible solutions to this:

  • Add Compile the app without running it first. I am guessing that I compiled it after running it. I’d have to add a command that resets the path to “”, compile the script, remove the line, recompile, and store it as an app.

  • Add a Boolean statement to the line that tests for the path as “” which causes the renaming routine to trigger if it finds my hard disk name (which is distinctive) in the property.

So, what do y’all think?

Thanks!

Larry the O

Hi. Scrap all that and use this. It sets the path every time the script’s run. It takes next to no time and is always right for the current user:

global prefsPath -- If it really needs to have global scope.

set prefsPath to (path to preferences as Unicode text) & "firstEdit Preferences.txt"

Properties (except in script objects) should really only be used for preset, constant values or for values that the script’s likely to change anyway as a note to itself for the next time it’s run. Otherwise, properties and globals are usually undesirable and are nearly always avoidable.

By the way, “Connection is invalid” often occurs when an application quits while it’s being sent a command. Are there any likely such areas in your script?

Thanks, Nigel. I hate it when I overlook the obvious (“path to preferences”), but thanks for pointing it out.

I’m using a lot of properties because my code is modular and it started getting complicated to pass all the different values to the different routines, especially as I changed the code in development. However, I will take your advice and look for other ways to deal with the issue.

But I’m still baffled as to why the other person’s machine is looking for Classic Support. If I send her the script and have her open it in Script Editor and save it on her machine, it works fine.

Larry

Hi, guys.

Mr. G.'s advice about script properties and globals is crucial here, and using them as a substitute for well structured code is fraught with risk. It may be very tempting “ especially with lengthy code “ to resort to using them when bolting on new functionality. But sooner or later, the need for a major redesign/rewrite will be almost inevitable.

It’s also important to appreciate how script properties and globals behave. The initial value of a script property is attributed at compile time, and will persist “ unless and until changed at runtime by some other statement. The value of a global variable is attributed at runtime, and will also persist “ unless and until changed again.

Because of this, care needs to be taken over environment-specific values, such as file paths “ so that they’re always reset at runtime. The following examples assume that the file “somePrefsFile.plist” will exist in the current user’s prefs folder:

A construct like this…


property my_prefs : (path to preferences as Unicode text) & "somePrefsFile.plist"

display dialog my_prefs

… will always use the value set when the script was last compiled. It’s therefore most unlikely to work correctly for another user “ until the script is recompiled in the new environment. (Such a script really shouldn’t be passed to an inexperienced user in compiled form.)

Even a technique like this…


property my_prefs : missing value

if my_prefs is missing value then set my_prefs to (path to preferences as Unicode text) & "somePrefsFile.plist"

display dialog my_prefs

… will work only in the environment in which it is initially run. Thereafter, it will very likely fail elsewhere. (If one really has to use this approach, send only a freshly compiled script “ and be prepared for a failure further down the line…)

As Nigel has suggested, this is about the only variation worth considering:


set my_prefs to (path to preferences as Unicode text) & "somePrefsFile.plist"

display dialog my_prefs

The bottom line is that, if a compiled script fails for another user “ but works after a recompile, it’s almost certain to contain a script property or global variable whose value is environment-dependent…

Yeah, I can see what you mean, having already traced a few problems down to just the things you’re talking about. So I’ll rework everything to minimize properties and globals (currently I have no globals, just properites.)

But I still don’t get why it’s looking for Classic Support. Is that related to a property or globals issue, too?

Thanks, guys. Time for me to tighten up my basics a little more.

Larry

What version of AppleScript do you have, looking around it seems older versions had a bug

set ASv to AppleScript version of (system info)

Maybe your version is affecting the way the script is compiled. and the one she makes from it inherits the bug.

Also as a test, What if you paste the script into a plain text file, zip it and get her to copy and paste from it into her Script Editor.