How do I diagnose a compiled Applescript that just quits at startup? - applescript

I wrote two applescripts so that my wife could launch mt-daapd and shut it down easily. They work fine in the Script Editor app but when I compile them into stand-alone apps, the apps work the first time I test them. Then they embarrass me as I proudly show them off to my wife. I see the "open" animation and then they just sit there. I've created other stand-alone apps before and this hasn't happened.
I tried changing the app type to a bundle (same problem). I even tried attaching to the executable via gdb to see if I could break on something magic to tell me what was going on. I looked in the Console for some information. Nothing was ther The scripts laughed in my face.
How do I fix this problem?
I've included one of the scripts below; the second is pretty much the same. I'm running 10.5.8.
property userpassword : ""
if userpassword is "" then
display dialog "Please enter your user password:" default answer "" with hidden answer
set userpassword to text returned of result
set the_password to "Undefined"
repeat until the_password is "Correct"
try
do shell script "/opt/local/sbin/mt-daapd -c /etc/mt-daapd.conf" password userpassword with administrator privileges
set the_password to "Correct"
on error
display dialog "Sorry, the password entered was not correct. Please try again:" default answer "" with hidden answer
set userpassword to text returned of result
end try
end repeat
if the_password is "Correct" then
display dialog "Your music is being shared!" buttons {"Done"} default button "Done"
end if
end if

I'm not sure how this is happening but the script is saving the value of userpassword between calls so once it has been set to whatever value, it retains that value and just exits the program. I discovered this after looking at how I created my other stand alone apps.

properties in applescripts are not fixed, they're like the properties of any other object. You can change them at run time, or evn from another script. so if your script1 was
property potato: "potayto"
say potato
and you ran another script
set potato of script1 to "potahto"
then running script1 again would make your computer say "potahto".
Properties can be useful ways of storing preferences in scripts.
Just delete the first if statement, it's redundant anyway. Check if the password is correct, rather than if it is empty.
thus:
property userpassword :""
set the_password to "Undefined"
repeat until the_password is "Correct"
try
do shell script "/opt/local/sbin/mt-daapd -c /etc/mt-daapd.conf" password userpassword with administrator privileges
set the_password to "Correct"
on error
display dialog "Sorry, the password was not correct. Please try again:" default answer "" with hidden answer
set userpassword to text returned of result
end try
end repeat
if the_password is "Correct" then
display dialog "Your music is being shared!" buttons {"Done"} default button "Done"
end if

Related

Applescript - remember state between executions?

Some Applescripts I have used have remembered state between executions, e.g., location for Open/Save dialogues.
Now I have written an AS that takes a string as input from the user (via a display dialog). I would like the script to remember that string between executions. Possible? How?
If you make the string a property, it will remember that string between executions, until the next time you open up and re-save the script.
Here’s an example:
property myName : ""
if myName is "" then
display dialog "What is your name?" default answer ""
set myName to the text returned of the result
end if
display notification "Hello, " & myName
Save the script as an “Application”, “Script”, or “Script bundle”. If saved as “Text” (or if run from Script Editor) it will not maintain properties between runs.
The first time you run it, it will notice that myName is the empty string and request your name.
Subsequent times you run it, it will already have your name in the property myName.
If you open the script again, and then resave the script, this resets all properties. If you need the script to retain data through edits, you’ll need to save it in a database, which could be as simple as a text file in a central location.
set nameFile to POSIX file "/Users/USERNAME/name.txt"
tell application "Finder"
if exists nameFile then
set nameFileHandle to open for access nameFile
set myName to read nameFileHandle
close access nameFileHandle
else
display dialog "What is your name?" default answer ""
set myName to the text returned of the result
set nameFileHandle to open for access nameFile with write permission
write myName to nameFileHandle
close access nameFileHandle
end if
end tell
display notification "Hello, " & myName
In this case the variable nameFile doesn’t need to be a property since it never changes. Because it doesn’t need to be a property, this version also does not need to be saved as non-Text, and can even be run from Script Editor.
It is also very simple; if you need to store and retrieve multiple items, you would need to follow up on the “File Read/Write” section of “StandardAdditions”. You can get there from Script Editor under “File:Open Dictionary…”.
For more complex memory, you may find the “Property List Suite” in the “System Events” dictionary useful.

Printing VBScript variables in QTP UFT

How can I check values of my variables at run time when using QTP UFT?
I simply want to create a variable, do logic and fill it with data, set a breakpoint in the line following the variable and then check or output its value somewhere.
I have tried:
print variableName
WScript.Echo variableName
The first produces error: Print function type mismatch
The second produces error: Object required: "WScript"
I'm not sure where the problem lies as I've just started to get into both UFT and VBScript (mostly did C# and javascript and everything is quite different here). Could someone tell me the correct solution and perhaps also explain these errors to me?
If you wanted to see all variables use the debug viewer in QTP.
View -> Debug Viewer
There you can list all the variables you want to watch. You should be able to see them in break points.
Note : Ensure you have Windows script debugger installed to use the debug viewer.
You can also add the variable to watch .. Insert a breakpoint>> start the script then right click on the variable under test and add it to watch(Add to Watch) . After Adding you will see a watch window and the value of the variable will be displayed.
I obsess over my variables... so much so that I sprinkly my code with print statements... Actually, I abstract print into my own UDF (so that I can optionally add logging to a file if needed)...
Here's my function: (it's actually a sub because it doesn't return anything)
Sub say(textToSay)
If talkative Then 'note that if I set global var "talkative" to false, then the whole log is disabled
print textToSay
End If
End Sub
Then, ALL my code typically looks like this...
say "click submit button"
Broswer("WebSite").Page("Search").WebButton("Submit").click
say "check for result"
if not Browser("WebSite").Page("Results").Exist then
say "results page didn't appear after exist timeout"
failtest
else
say "successfully found results page"
end if
Honestly, I'm shocked that your "print variableName" statement gave an error, print is actually available in the VBScript api, so it should have worked.
All of my output goes to the Output pane in UFT. I would give my right-arm to find a way to programmatically clear that output pane between runs, but noone seems to know how to do it.
The benefit of all this logging is that I can watch my code run and see EVERY branch taken by the code, and I can add statements to print my variables.
Here's an example that shows how I would answer your question:
result = browser("WebSite").Page("Results").WebElement("Result").GetROProperty("innertext")
say "result:" & result
if result = "Approved" then
Reporter.ReportEvent micPass, "Check for approved", "Approved!"
else
Reporter.ReportEvent micFail, "Check for approved", "NOT Approved!"
End If
Notice the say statement in there - I'll be able to see that immediately during code execution without waiting until the results are shown at the end.

Missing Value error running an AppleScript

I have written a little AppleScript which returns "missing value" and I have no idea why this happens. The script is doing what it should do, but the output is not nice in my application where I use it.
The principle of this script is just to take the argument and run the file (with "VLC Media Player") which is provided through the argument.
So for example a use would be osascript open_video.scpt ~/Path/To/File/File.mp3
on run argv
tell application "VLC"
activate
open argv
end tell
end run
This question is old but brought to the top of the questions by a new answer before I added this answer.
The recently posted answer suggests this issue might be caused if there isn't an ending newline character, and this is not at all true in this case as I've tested both with and without an ending newline character and get the exact same results, both with compiled and plain text AppleScript scripts.
You do not need to have an ending newline character and it has nothing to do with why your code is returning missing value.
Looking in the AppleScript Dictionary for the open command, it shows the following:
open v : Open an object.
open alias : The file(s) to be opened.
→ document
Where the → represents returns as in it returns info about the documents, e.g. its name.
In this case VLC is returning missing value instead, and probably because VLC does not integrate AppleScript as nice as e.g. Apple's own apps.
If you do not want to see missing value then add a return "" to the code and it will return a blank line. Or you could add e.g., return "VLC is now playing: & (argv as string); however, because VLC's AppleScript integration is not the best, I'd just go with return "" as VLC does not respond to standard AppleScript error handling well. Again, an observation by testing error handling code that works with other apps but not VLC.
Or just simply directly use the command line open command, e.g:
open "/Applications/VLC.app" "/path/to/media_file.ext"
Which will open the VLC app, start the media_file.ext file, and return the prompt.
In my testing, you have to coerce the passed variable to a string.
osascript open_video.scpt '~/Path/To/File/File.mp3'
with a script as such:
on run argv
tell application "VLC"
activate
open (argv as string)
end tell
end run
Did you make sure that you have a newline on the end of the last line? For me I got this error when I had a script that ended abruptly at the last character of the script, instead of having a newline at the end.
AFAIK this doesn't affect the functionality of your script, just what it returns. In my case I got some other output instead after I made this change, but the output appeared to be merely informational.

VBScript and presenting an input box

I am writing a script to capture the login time. In the final production, there would be no input from any user. However I am testing it and I wanted to know how I add extra code to determine that
If its in 'debug' mode AND
The user that is logging in is me (lets say my username is joe.smith on the domain called EXAMPLE)
then present an input box to allow me to type the date, time for logging in.
All other users would never see this and it would capture today with the system time.
I would also like to hide the code so if the script is opened by the wrong person, they wouldnt be able to make heads or tails of whats going on.
You can use a command line parameter as Matt says to set the script into debug mode, eg
dim isdebug: isdebug = WScript.Arguments.Named.Exists("debug")
WScript.Echo("in debug mode: " & isdebug)
Which you can invoke with
wscript debugscript.vbs /debug
To get the current user name, you can use either the WMI Service or the WScript.Network object.
Once you have the username, you can conditionally throw up an InputBox and collect the value returned:
dim date_: date_ = Now()
if isdebug and username = "me" then
dim value: value = CDate(InputBox("enter the date and time (dd/mm/yyyy hh:mm:ss)", "please", Now()))
' validate the input here
date_ = CDate(value)
end if
And finally, to obfuscate your code you could use the Scripting.Encoder although it looks like this doesn't seem to be supported on Vista or Windows 7. There does seem to be a few hits on googling the phrase obfuscating vbscript, anyway.
Most of this sounds like it can be resolved by the logic of the script.
Have a command line parameter (debug is an appropriate name) and then have some if logic in the code to do as you wish (present the input box).
For the code obfuscation, I don't know how this could be done in vbscript. Windows scripting host works with JavaScript as well though and there are plenty of tools on the web for making JS harder to read. Maybe you want to look a using JS...
HTH,
Matt
I think you can check the property App.LogMode to see if you are in 'debug' mode or not. If it is 0 then you are running debug mode and if it is 1 you are not.

Adding user Authentication using Applescript

I want to add user authentication in my applescript to perform some task. If the username and password is correct then only the next task should happen. How to do this using applescript?
You haven't really said how much security you want.
The most basic of solutions:
display dialog "Enter username:" default answer ""
set enteredUsername to text returned of result
display dialog "Enter password:" default answer ""
set enteredPassword to text returned of result
if enteredUsername is "CORRECTUSERNAME"
if enteredPassword is "CORRECTPASSWORD"
-- do something
end if
end if
Save it as a read-only script and it'll prevent casual users from looking at the contents of the script, but this is not really secure at all if someone really wants to break through your protection.
If your Mac is running Leopard (Mac OS X 10.5+), then you could use the long user name property of the system info command, which returns the full name of the current user. Having said that, you could do this...
set the current_user to (get the long user name of (system info)) as string
set the input_password to the text returned of (display dialog "Please enter the password for " & the current_user & ":" default answer "" buttons{"OK"} default button 1 with hidden answer) --The user cannot bypass this dialog.
--The 'hidden answer' property, when true, changes every character you type in the dialog box into ◘'s.
try
--This next line will verify that the password entered matches the current user's password.
do shell script "history -c" user name the current_user password the input_password with administrator privileges
on error --incorrect password
display dialog "Sorry. You entered the wrong password." buttons{"Cancel"}
end try
--Put whatever you want to do after authentication here.
If you have any questions, just ask me :)
If you are wanting a username and password input then use this:
set a to the text returned of (display dialog "Please enter your username" default answer "")
set b to the text returned of (display dialog "Please enter your password" default answer "")
if a="username" then --set the username to your username
if b="password" then --set the password to your password
--what ever is after your password protection
end if
end if

Resources