How to pass variable from applescript to km

How can I pass a variable from applescript to km? :neutral_face:

See http://www.keyboardmaestro.com/documentation/6/scripting.html

Thank you,
I figured it out…
Didn’t understand the KM document because I don’t take the time to read word for word…

I needed a error trap message when mounting my drives.

tell application "Keyboard Maestro Engine"
    set Mounteddrives to 1
end tell

Hey Bill,

Actually you're only setting the AppleScript variable Mounteddrives to a value of 1

To set a Keyboard Maestro variable from AppleScript you need to do something like this:

tell application "Keyboard Maestro Engine"
  try
    set value of variable "myVarName" to myValue
  on error
    make new variable with properties {name:"myVarName", value:myValue}
  end try
end tell

Be sure to pay attention to the fact that KM variables are quoted-strings. If you don't you'll be scratching your head at some point.

You can of course trap errors more specifically by adding parameters to the error-handler:

on error eMsg number eNum

--
Best Regards,
Chris

1 Like

I still having trouble.
When I run this script through Script editor variable "Mounteddrives" is true in KM. BUT when I run script through KM variable "Mounteddrives" is true then sets to not true?? empty??

tell application "Finder"
	delay 10

	try
		-- Check if SERVER is available
		set max_retry to 10
		set k to 0
		repeat while (do shell script "ping -c 1 xxx.xxx.xxx.xxx") contains "100% packet loss"
			delay 5
			set k to k + 1
			if k > max_retry then error "Server is not responding for predefined period." number 8000
		end repeat

		--tell app "Finder" to open location "protocol://username:password@server/share" 
		-- Mount volumes
		mount volume "smb://user:password@QNAP(SMB)._smb._tcp.local/drive1"
		mount volume "smb://user:password@QNAP(SMB)._smb._tcp.local/drive2"
		mount volume "smb://user:password@QNAP(SMB)._smb._tcp.local/drive3"
		mount volume "smb://user:password@QNAP(SMB)._smb._tcp.local/drive4"

		-- Error handler
	on error errs number errn
		display dialog errs & " " & errn with icon 2
		display notification "SERVER not responding to ping."
	end try

	tell application "Keyboard Maestro Engine"
		set value of variable "Mounteddrives" to "Success"
	end tell

end tell

KM

I'm not no programmer... But trying hard to learn...

Found the problem :slight_smile:
Save to Variable: … oops…
But the script could be modified for error catching… :smile:

Hey Bill,

You were already saving to Mounteddrives from within the script, so as far as I can see there was no reason to output the result to the variable.

However.

One thing you have to look out for is variable state.

If you assign "Success" to that variable it will keep it forever.

If you have a test that uses the variable it won't necessarily be reliable because of the saved-state.

You need to initialize the variable at the beginning of your script (or macro) OR reset the state when the macro exits.

Generally I'd go with option one.

Your AppleScript does not require a Finder-Tell-Block. The commands used are from the Standard Additions.osax.

If you're running from the Finder then it's desirable to wrap the on-error display dialog call in such a block, because Keyboard Maestro will eat it otherwise. Display Dialog needs a context when run from Keyboard Maestro.

try
  
  delay 10
  
  -- Check if SERVER is available
  set max_retry to 10
  set k to 0
  repeat while (do shell script "ping -c 1 xxx.xxx.xxx.xxx") contains "100% packet loss"
    delay 5
    set k to k + 1
    if k > max_retry then error "Server is not responding for predefined period." number 8000
  end repeat
  
  -- tell app "Finder" to open location "protocol://username:password@server/share" 
  -- Mount volumes
  mount volume "smb://user:password@QNAP(SMB)._smb._tcp.local/drive1"
  mount volume "smb://user:password@QNAP(SMB)._smb._tcp.local/drive2"
  mount volume "smb://user:password@QNAP(SMB)._smb._tcp.local/drive3"
  mount volume "smb://user:password@QNAP(SMB)._smb._tcp.local/drive4"
  
  return "Success"
  
  -- Error handler
on error errs number errn
  tell application "Finder"
    activate
    display dialog errs & " " & errn with icon 2
  end tell
  display notification "SERVER not responding to ping."
  
  return "Failed"
  
end try

At the beginning of your macro use a Set Variable to Text Action to set "Mounteddrives" to NULL or FALSE or something else relevant.

You'll see that the script above will return a value of "Success" if it successfully finishes mounting the drives, and it will return "Failed" if the it errors-out.

But the initial condition of the "Mounteddrives" variable should be something else.

You can of course set the value of the variable from within the script rather than as a result of the script.

BTW: I prefer to use camel-case or underscores in variable names to make them more readable:

MountedDrives
mountedDrives
Mounted_Drives
mounted_Drives
mounted_drives

Persistent variables will often bite the hand that feeds them, unless they are given the proper care.

:sunglasses:

-Chris

Thank you this works great and has changed everything in a very good way… :smile:

Good Idea > camel-case or underscores in variable names

I’m a beginner to KM Now I see my unneeded variables in KM variable selection how do I remove them from the context menu? :flushed:

Again Thank you Chris :smile:

Hey Bill,

Look in the Variable pane of KM's preferences. You can manage them there.

-Chris

LOL… I found it… Thank you… :smile:
Again Thank you… :smile:

I think this could be smaller... What do you think ccstone?
I had a problem with the last one it would try to mount volumes over and over, this way it checks first but I think it's fat...

tell application "Finder"

if not (disk "FaceBook Pictures" exists) then
mount volume "afp://192.168.2.101/FaceBook Pictures" as user name "admin" with password "mypassword"
display notification "FaceBook Pictures Mounted"
end if

if not (disk "Art work Files" exists) then
mount volume "afp://192.168.2.101/Art work Files" as user name "admin" with password "mypassword"
display notification "Art work Files Mounted"
end if

if not (disk "Download" exists) then
mount volume "afp://192.168.2.101/Download" as user name "admin" with password "mypassword"
display notification "Download Mounted"
end if

if not (disk "Mac Documents" exists) then
mount volume "afp://192.168.2.101/Mac Documents" as user name "admin" with password "mypassword"
display notification "Mac Documents Mounted"
end if

if not (disk "Movies" exists) then
mount volume "afp://192.168.2.101/Movies" as user name "admin" with password "mypassword"
display notification "Movies Mounted"
end if

if not (disk "Qsync" exists) then
mount volume "afp://192.168.2.101/Qsync" as user name "admin" with password "mypassword"
display notification "Qsync Mounted"
end if

if not (disk "Stuff" exists) then
mount volume "afp://192.168.2.101/Stuff" as user name "admin" with password "mypassword"
display notification "Stuff Mounted"
end if

if not (disk "Rachel Files" exists) then
mount volume "afp://192.168.2.101/Rachel Files" as user name "admin" with password "mypassword"
display notification "Rachel Files Mounted"
end if

if not (disk "USBDisk1" exists) then
mount volume "afp://192.168.2.101/USBDisk1" as user name "admin" with password "mypassword"
display notification "USBDisk1 Mounted"
end if

if not (disk "USBDisk2" exists) then
mount volume "afp://192.168.2.101/USBDisk2" as user name "admin" with password "mypassword"
display notification "USBDisk2 Mounted"
end if

if not (disk "Multimedia" exists) then
mount volume "afp://192.168.2.101/Multimedia" as user name "admin" with password "mypassword"
display notification "Multimedia Mounted"
end if

end tell

Hey Bill,

I reckon.

There's nothing wrong with that methodology, except that it becomes more and more difficult to maintain as the list gets longer.

So let's change things around and make it easy to maintain.

I don't have a network here to test with, so you'll have to be the guinea pig.

------------------------------------------------------------
try
  
  set networkDisks to text 2 thru -2 of "
afp://192.168.2.101/Art work Files
afp://192.168.2.101/Download
afp://192.168.2.101/FaceBook Pictures
afp://192.168.2.101/Mac Documents
afp://192.168.2.101/Movies
afp://192.168.2.101/Multimedia
afp://192.168.2.101/Qsync
afp://192.168.2.101/Rachel Files
afp://192.168.2.101/Stuff
afp://192.168.2.101/USBDisk1
afp://192.168.2.101/USBDisk2
"
  tell application "Finder" to set diskNameList to name of disks
  set AppleScript's text item delimiters to "/"
  repeat with i in paragraphs of networkDisks
    set {diskAddress, diskName} to {contents, last text item} of i
    if diskName is not in diskNameList then
      # mount volume diskAddress as user name "admin" with password "mypassword"
      display notification diskName & " Mounted"
    end if
  end repeat
  
on error e number n
  set e to e & return & return & "Num: " & n
  if n ≠ -128 then
    try
      tell current application to button returned of ¬
        (display dialog e with title "ERROR!" buttons {"Copy Error Message", "Cancel", "OK"} ¬
          default button "OK" giving up after 30)
      if ddButton = "Copy" then set the clipboard to e
    end try
  end if
end try
------------------------------------------------------------

I've left the mount line commented, so you'll need to uncomment it when you're ready to try it out.

This kind of table-based system is much easier to work with and maintain than a bunch of If-statements or AppleScript records. I've used similar methods for many tasks over the years, although I usually use the Satimage.osax AppleScript Extension and regular expressions to parse tables.

-Chris

1 Like

Bump — fixed some typos and added basic error-checking to the script.   -ccs

1 Like

WOW it worked perfectly and Much leaner! :smile:
I’ll look at this line by line to understand how it works never stop learning Loving it.
I wonder is there a resource for applescript for dummies? LMAO…

You are very kind to helping out.
Once again Chris thank you very much. :smiley:

Hey Bill,

There is such a book.    :smile:

Although I haven't had my hands on it and don't have an opinion about its worth.

This might interest you:

References for Learning & Using Applescript

-Chris

1 Like

I found this book very helpful:

Learn AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X (Learn (Apress))

Chris, thanks for creating and sharing such a tremendous resource.

JMichael

Good list of references !

Stepping back a bit, perhaps the key is really to get a clear grasp and practiced familiarity with the core concepts – after that the syntax of any particular language is really just a variation in detail.

My list of the core concepts would probably be:

  • What is a variable, really, and what is going on in assignment of values to variable names ?
    (and what kind of values are there ? Numbers, strings, true|false ‘booleans’, and lists, for a start)
  • How do true | false (‘boolean’) values work in combination with operators like AND, OR, NOT ?
  • How can one break a problem down into a nest of sequences, branches and loops ?

and then how can you:

  • hide details with ‘sub-routines’ ?
  • apply a function to a value and collect the function’s result ?

and for extra credit

  • how do you write a function whose definition includes itself ?
  • why would you want to ?
  • how can you use a function as the value of a variable ?
  • and why would you want to do that ?

And for context:

What does Lisp look like, and how, broadly, does it work ?

( There is a sense in which all language translators/interpreters rewrite to something very much like Lisp before rewriting down to machine code, and while a dialect like Applescript is relatively niche and ephemeral, we can be fairly confident that even in other galaxies the deep structure of coding is bound to be Lisp-like. See section 9 (conclusion) of Phil Wadler’s paper )

Expertise is not so much knowing the details as grasping the fundamentals, and the best introductions to Applescript might even be books like:

https://mitpress.mit.edu/books/little-schemer on Lisp

or http://eloquentjavascript.net/ on Javascript

( The concepts are the same, and once you have those, the details will come easily : -)

2 Likes

Following on from @ComplexPoint’s, err, point, one of the best ways to learn basic programming I’ve seen recently is the Hour of Code, which teaches these sorts of fundamentals. It happens that they use JavaScript, which is very handy for web programming, and now becoming very handy for Mac automation programming as well.

2 Likes

I'm not sure that I agree. :wink:

I find the so-called "natural language" of AppleScript to actually work against the fundamental knowledge I have of programming, and the many years of programming in other languages. Since I have never thought about coding in a natural, english-language like sense, I find AppleScript to be counter-intuitive.

If a person has never programmed before, of course they need to learn the basic concepts of program design. But learning another language that is nothing like AppleScript might be more of a hindrance than help.

It seems to me that few of the terms used in AppleScript are used elsewhere, and most of the terms common in other languages (and even design) are not used in AppleScript.

So, IMO (and I am far from being an AppleScript expert), a person with no programming experience is better off starting with AppleScript focused training, be that books, tutorials, videos, or other.

As Chris mentioned, much of learning AppleScript is learning the unique code for a specific application. For me, the fastest way I have learned is by example, inspecting, testing, code written by others.

Just my 2¢.