Why does my Automator service work in Automator but not when called from the OS?

I have made an Automator service that runs an Applescript with the Run Applescript module. This is the script:

# Press ^F8
tell application "System Events"
    key code 100 using control down
end tell

delay 0.1

# Press "down"
tell application "System Events"
    key code 125
end tell

delay 0.1

# Press ^F9
tell application "System Events"
    key code 101 using control down
end tell

When I have the service open in Automator and press Workflow -> Run all works as it should. However, when I open the service from the menubar, i.e. in Safari, by going to Safari -> Services -> script name nothing happens. Nothing is written to the Console, so I can't figure out why the service is not working. How can I track down the error and make the service run outside of Automator?


Solution 1:

What is ⌃F9 meant to do? This worked for me when I wrapped it in a service:

tell application "System Events"
    key code 100 using control down -- ^F8
    delay 0.1
    key code 125 -- down
    key code 125
    keystroke return
end tell

You could try running the workflow with automator -v:

$ automator -v ~/Library/Services/lock.workflow/
Starting Automator…
Run AppleScript is running

Run AppleScript is finished

The Automator workflow has completed.

There are several issues with using Automator services to assign shortcuts to scripts though. See this question. If you run the service with a shortcut that has modifier keys, there might not be enough time to release them before the key code commands.

You could also use a script like this:

tell application "System Events" to tell process "SystemUIServer"
    tell (menu bar item 1 where description is "Keychain menu extra") of menu bar 1
        click
        click menu item 1 of menu 1
    end tell
end tell

Solution 2:

Using the Right Tool for the Right Job

  1. You could try adding a beep to your AppleScript to hear if it is getting called.

  2. I've had Services not run before when there are two things trying to use the same key-combinations. You could try adding more modifier keys to make a conflict less likely (for testing and debugging.)

  3. When I see code that is dependent upon calling the command called "delay", I get a bad feeling like the code isn't always going to work.

  4. AppleScript was intended by Apple to be an alternate user interface, an alternative to mouse and keyboard using AppleEvents to do Interprocess Application Communication (IAC). I believe that you may want to use AppleScript and Automator Services to give you a GUI to work with, but it seems likely to me that you should use something lower-level than AppleScript and AppleEvents for what you are doing.

So, I'm talking about adding some sort of shell script to the mix to make it all work reliably.

--- Edit ---

Since @markhunte has criticized my answer as not really being an answer, I'll try to do better.

  1. I suggested that you put some calls to "beep" in your AppleScript to debug whether your script was even being called or not. I tried that and it didn't work.

I found the following link which talks about making your own log function. I think that will work better. http://hints.macworld.com/article.php?story=2004121710493371

Here's my version of the code to do your own log using AppleScript, from what I gather, the log function that is built into AppleScript just shows the results at the bottom of the AppleScript editor windows, and I think that the system log is hard to understand. This log function works for me, I've actually tried it:

on logToFile(themessage)
    if themessage is equal to "" then
        set theLine to ""
    else
        set theLine to (do shell script "date  +'%Y-%m-%d %H:%M:%S'" as string) & " " & themessage
    end if
    do shell script "echo " & theLine & " >> ~/Library/Logs/AppleScript-events.log"
end logToFile

on run {input, parameters}

    logToFile("")
    logToFile("Entering Lock Keyboard Service")

    set F8 to 100
    set F9 to 101
    set DOWN_ARROW to 125

    # Press ^F8
    logToFile("About to simulate control-F8")
    tell application "System Events"
        key code F8 using control down
    end tell

    delay 0.1

    # Press "down"
    logToFile("About to simulate down-arrow")
    tell application "System Events"
        key code DOWN_ARROW
    end tell

    delay 0.1

    # Press ^F9
    logToFile("About to simulate control-F9")
    tell application "System Events"
        key code F9 using control down
    end tell

    logToFile("Exiting Lock Keyboard Service")

    return input
end run

I wrapped the code in an

on run
end run

because the code seemed to work better for me that way.

Besides logging, to debug, you could try using some visible characters like "A", "B", and "C" and you could see if they are getting typed into Safari.

One more idea for you. When I first tried the script, the F8 key was tied to something. I had to go into System Preferences > Keyboard > Keyboard Shortcuts and untie the ^F8 key-combination from what it was tied to. (This is like what I said in my first answer which I think had some good ideas like trying different key combinations.)

Here's a link to a screen-shot. It's in my Public Dropbox folder. Let me know if you can see it as I am trying out sharing links using Dropbox.

https://www.dropbox.com/s/jm3smqa4g5v2k33/KeyboardShortcuts.png

What is it that you're trying to do? Lock a keyboard with this sequence of key-combinations?

The workflow did run for me in Safari (after I changed the control-F8 key in the Keyboard Shortcuts in System Preferences) and in Safari, I did get a down-array key, but the keyboard didn't lock. Does that require an additional piece of software for this to work?

[email protected]

--- Edit ---

I added the man page for the "automator" command to my website that is in its infancy.

man page for the automator command http://learnbymac.com/doc/unix/automator.man.html

--- Edit ---

I have a few more ideas for you:

  1. In the System Preferences, there are some preferences for enabling features that you help you (at least during debugging).

A. There is "sticky keys" which allows a modifier key to stick and not go away as fast, that might help. I don't know.

http://learnbymac.com/images/screen_shots/StickyKeys.png

B. Thee is an option to have a picture displayed on the screen (and sound played) when a modifier key is detected.

http://kaydell.us/learnbymac/images/screen_shots/DisplayPressedModifierKey.png

  1. You could use a program that is specially made to handle defining key-combinations. Years ago, I used to use a program called QuicKeys. They seem to have less Mac support now, but you could google for "Alternatives to QuicKeys" if that would work for you to have another program handle defining the keyboard equivalents.

P.S.: I just turned off all of those preferences from the Accessibility System Preferences, I can't stand using them (maybe some would be OK but I think that the "Sticky Keys" was causing my Caps Lock to stick typing everything in all caps. :( ).

http://kaydell.us/learnbymac/images/screen_shots/DisplayPressedModifierKey.png

It might be best to use Spark.app to handle command-key equivalents
http://www.shadowlab.org/Software/spark.php