REALbasic and Applescript question

I have a small Applescript that I call from within a real studio project. Here’s what it looks like:

property pw : "123"
tell application "System Events" to keystroke pw & return
set pw to ""

The problem is, the property gets reset to the original “123” every time the project is run. REALbasic isn’t ignoring the property definition at the beginning of the code. What can I do to fix this so that when run a 2nd time, pw is still set to “”?

I’m not sure but I think REAL is recompiling the applescript every time it runs this code so properties won’t work for you. A property is set to initial value every time it is compiled again and therefore in your case it is set to “123” every run. An alternative would be storing it into a file.

Thanks for the reply.

Okay, here’s a new angle:

set myPath to "PATH:TO:THIS:SCRIPT?" as alias
tell application "System Events" to keystroke "123" & return
do shell script (do shell script "rm " & quoted form of POSIX path of (myPath))

If the script can delete itself, that would solve a world of worry. The problem is:

Do plugins inside a real studio app have a file path? Or are they completely compiled into the build? In other words, is there any way for the script to delete itself from within the real studio app?

Hi wontonunist

When I have used Applscripts in Real Basic projects, I always use an explicit on run handler.
This is also recommended by Real Studio documentation, so try using your script this way
and see if the problem persists.

for e.g.

[code]property pw : “123”

on run {}
tell application “System Events” to keystroke pw & return
set pw to “”
end run[/code]
I this also does not do the job then ditch the property, and pass the on run handler a parameter.
And save the state of that parameter in you Real Basic project.

for e.g.

on run {yourVariable} --yourVariable passed from Real basic project set yourVariable to yourVariable as string tell application "System Events" to keystroke yourVariable & return --set pw to "" dont use this line, just save the state of yourVariable in your RB Project end run
This will not compile in the Applescript Editor, but it will run when dragged into your Real Basic Project.

Call the script from RB project like this

[code]Dim yourVariable = “pw” as string //set yourVariable to an RB string value

YourScriptName(yourVariable) //Call the Applescript with yourVariable[/code]
I have written several Applescripts for Real Basic Projects, and they can be a bit tricky.
The support for Applescripts in Real Basic is not good, but powerful things can be achieved.

If you tell me what you want to do with your script, I could always write the script for you, and
email to you, or contact me in the Real Studio User Forums under the same Mark FX username.

Regards Mark

Hi Mark

Thanks for the offer and the reply. I’m gonna give it a shot myself (with as much help as I can get) first off, but I’ll let you know.

Question:

How would I save the state of yourVariable in the RB project? Or how can I pass a variable from the applescript back into REALbasic?

I know you could probably do this easily, but I’m trying to get an understanding of how the two interact.

Or can I use a RB static variable to determine if the app is being run for a second time?

How about a way to delete a file that has been added to the real studio project?

You can use a Real Basic constant to save fixed string values in RS, but this subject
should be discussed in the Real Studio forums.

Because this is an Applescript Forum I will return to the example I posted, this example
will retain its property value in a compiled script, but as DJ Bazzle Wazzle eluded to, when
you build & run a project in the Real Studio IDE, it recompiles your RB code, and the
Applescript code each time, and so the script will not retain its value when recompiled.
Only when you Build your RB project as a competed application will the script then save its
property values.

You have not explained to me what you want the script to do, so I can only guess at some
example code, but this may or may not be what your looking for.

[code]property stringValue : “” as text

on run {}
try
if stringValue is equal to “” then
tell application “System Events” to keystroke stringValue & return
–reset the stringValue property if you need to
return “Completed empty stringValue” as text
else if stringValue is equal to “pw” then
tell; application “System Events” to keystroke stringValue & return
–reset the stringValue property if you need to
"return “Completed pw stringValue” as text
else
–the stringValue property is none of the above values
end if
on error errorMessage number errorNumber
return “Error” & space & errorMessage & space & errorNumber as text
end try
end run[/code]
The way to call this script from RB would be something like this.

[code]Dim Result as string

Result = YourScriptName

//Check the returned Result from the Applescript

if Result = “” then
//do something here with empty string Result
elseif Result = “pw” then
//Do something here with the pw string Result
elseif Left(Result, 5) = “Error” then
//An Error occured in the Applescript execution
else
//Returned Result value is something else
end if[/code]
I dont know if this might help, but unless your more specific about what your trying to achieve.
No one at this forum or the RS forum, will be able to offer much help.

Regards Mark

Yeah, sorry. I realize I wasn’t being really clear at all. Thanks for the example code.

I did figure out something that’s sort of a solution for my problem. I’ll explain. I have a password-protected PDF that the Real Studio app opens. Then it executes the AS script asset inside the project which keystrokes the password into the open password text field and hits return to unlock the PDF.

The goal is to only have the script unlock the PDF once. After it runs one time, it doesn’t run again. Period.

Here’s how I did that. The following is a script that’s run by the Real Basic app.

set code to ((path to me) as text) & "Contents:MacOS:.7ze0q.scpt" as alias set pw to "123" & return run script (code) with parameters {pw} do shell script "rm " & quoted form of POSIX path of (code)
It passes the password over to .7ze0q.scpt (which is inside the Real Basic app bundle) when it runs it. .7ze0q.scpt looks like this:

on run {pw} tell application "System Events" to keystroke pw end run
The above script is deleted after the first run, then disabling the unlocking process.

I hope that gives you a good idea of what I’m trying to accomplish. If you know of how I could do the same thing without dealing with two scripts, that would be much appreciated.

Thanks for your time.

I dont understand why tou are using two scripts, and then deleting one of them after execution.
Simply bulid and import one script into your RB project, and only run it the one time.
When you save the script, save it in Applescript Editor as a run only script, this way no one can
open or edit the script, also when you build your completed RB app, the run only script will be
compiled into your app’s code, so no way anyone could access its contents.

The other problem with deleting one of the scripts, is that in a situation where you try to run the
\script a second time, you will get an error message because the script no longer exists, you dont
want to introduce potential problems like this into your app.

As stated previously either have a boolean property in your script, or in your RB project that retains a value
telling you that the script has been run, so that you do not run it a second time, I believe you can create
a property in RS IDE that works like an applescript property, that will retain its value between runs.
But please remember that the Applescript properties only retain values when yo are not re compiling them
each time you run your app in the RS IDE.
But I am sure you can design your RB app to only call the script once, and then forget about it.

This sort of script should do the job.

[code]property scriptHasBeenRun : false as boolean

on run {}
set myPassword to “123” & return as text
if scriptHasBeenRun is equal to false then
try
tell application “System Events” to keystroke myPassword
set scriptHasBeenRun to true as boolean
return scriptHasBeenRun as text
on error errorMessage number errorNumber
set scriptHasBeenRun to false as boolean
return “Error” & space & errorMessage & space & errorNumber as text
end try
else if scriptHasBeenRun is equal to true then
return scriptHasBeenRun as text
end if
end run[/code]
calling this Applescript in RB would be something like this.

[code]Dim Result as string

Result = YourScriptName

If Result = “true” then
//The script has been run so dont run it again
elseif Left(Result, 6) = “Error” then
//An error occured during the script execution so handle it
end if[/code]
The alternative is set up a boolean RB property in the RS IDE and do something like this

on run {myPassword} set myPassword to myPassword as text try tell application "System Events" to keystroke myPassword return "Completed" as text on error errorMessage number errorNumber return "Error" & space & errorMessage & space & errorNumber as text end try end run
The code to call the above in RB would be something like this.

[code]RB property as boolean = false

Dim Result as string
Dim myPassword = “123” as string

Result = YourScriptName (myPassword)

if Result = “Completed” then
//Reset your RB property to true
//The script has been run so dont call it again
elseif Left(Result, 6) = “Error” then
//An error occurred in the script execution so handle it
end if[/code]
You do not set up a property in RB like this, you have to click the add property tab in the RS code editor, and
add it to a RB Module with a global scope setting, I have only written it like above for example purpose, if my
memory serves me right I beleive that RB properties retain their value between runs, even in the RS development
enviroment, but you should check the RB documentation to confirm this, as I have not used RB for a long while.

Well I hope this might be of some help

Regards Mark

Sorry the last bit of RB code is not exactly right, it should be more like this.

[code]RB property as boolean = false

Dim Result as string
Dim myPassword = “123” as string

if RB property = false then
Result = YourScriptName (myPassword) //Call the script with your password
if Result = “Completed” then
RB property = true
//The script has been run so dont call it again
elseif Left(Result, 6) = “Error” then
//An error occurred in the script execution so handle it
end if
elseif RB property = true then
//Script has been run so dont call it again
end if[/code]
Thats better

Regards Mark