Throwing error at tell for System Events

Hi,

I have a script that makes a call to System Events for VLC menu actions. I’m using a well done script I found elsewhere that manages the menu calls. I’m using SD V6 on Sierra.

Notes:

  1. I have enabled the script for assistive access
  2. The script runs fine until I make an error in scripting that throws an error
  3. After an error is thrown, and I fix the script, the script will error out at the "Tell Application “System Events” line
  4. No matter what I do, quitting, restarting workstation, re-compiling, etc the error is still thrown at that line
  5. The only way I’ve found to correct this is to copy the offending script into a new empty script and then it runs fine until another error is thrown.

Must be something obvious, but it’s stumped the chump. Thanks for any advice you can provide.

The calls to the subroutines:
my menu_click({“VLC”, “Edit”, “Select All”})
my menu_click({“VLC”, “Edit”, “Clear”})

The subroutines:
on menu_click(mList)
local appName, topMenu, r

-- Validate our input
if mList's length < 3 then error "Menu list is not long enough"

-- Set these variables for clarity and brevity later on
set {appName, topMenu} to (items 1 through 2 of mList)
set r to (items 3 through (mList's length) of mList)

-- This overly-long line calls the menu_recurse function with
-- two arguments: r, and a reference to the top-level menu
tell application "System Events" to my menu_click_recurse(r, ((process appName)'s ¬
	(menu bar 1)'s (menu bar item topMenu)'s (menu topMenu)))

end menu_click

on menu_click_recurse(mList, parentObject)
local f, r

-- `f` = first item, `r` = rest of items
set f to item 1 of mList
if mList's length > 1 then set r to (items 2 through (mList's length) of mList)

-- either actually click the menu item, or recurse again
tell application "System Events"
	if mList's length is 1 then
		click parentObject's menu item f
	else
		my menu_click_recurse(r, (parentObject's (menu item f)'s (menu f)))
	end if
end tell

end menu_click_recurse

Your code looks wrong. For GUI scripting, you also need to activate the target application and address its process. Something like:

tell application "VLC" to activate
tell application "System Events" to tell process "VLC"
...

Fred,

I’ve done a lot of GUI scripting and I have found if the activate doesn’t come before sending script commands to the app all kinds of things can go wrong that make no sense. Activate prepares the App to receive the commands. It depends on the App how much of a problem it will be, but it never hurts to add it in, and often causes problems if you don’t.

Bill

I should have been more explicit. I have the activate before the calls?

tell application "VLC" to activate

delay 2
my menu_click({"VLC", "Edit", "Select All"})
delay 2
my menu_click({"VLC", "Edit", "Clear"})
delay 0.5

Since the subroutines are generic, for any application, how can I modify the call to tell application “System Events” to reference the target (generic) application, rather than have it hard-coded?

You can probably use something like (untested):

tell application "System Events" 
tell process 1 whose frontmost is true
...

Fred,

GUI scripting is a very tricky business normally. I have VLC 2.2.4 and it has a dictionary built into it. “System Events” is normally the last thing to try to “control” another application. System events is geared more to sending a command. Driving app by initiating menu clicks often failed to work for me. You have normal system delays, delays from VLC and delays from system events which will probably force you to add big delays in the script to get all that to work together and it might end up running far slower then it needed to.

If I wanted a generic script I would have a script that figured out what it was going to work with and then execute generic handler. The target application would be a low level detail. All you do is pass the target application to the top level. Using Script Debugger’s dictionary inspector and a amazing utility called “UI Browser” almost anything can be scripted and scripted quickly with this method.

This will give you the window by name:

tell application "VLC" to every window whose name is "VLC media player"

VLC has hidden windows that can easily get someone mixed up. To get the first window I would bet this would work. It work almost anywhere.

tell application "VLC" to window 1

What are you actually trying to accomplish? What you are doing looks the hard way to me unless I am missing something.

When I’ve had a script controlling multiple apps and I’m using generic routines I’ve always passed the target application along with the other parameters to the a generic routine. Then the generic routines does all the set up and just makes calls when necessary to interface with an App. You could have a global variable (or a property if you want the value to be remembered after quitting and restarting) that can be set and all generic commands will be directed to the proper application until it’s changed to point to a different application.

If you said what your ultimate goal it would probably be easier to help you.

The trick to GUI scripting is to use it as little as possible and still get the job done. If you do too much then it starts fighting you.

If I am missing something here let me know.

Bill

1 Like

Bill,

Thanks for the feedback. I should have explained what I need to do and how I got to this point. I’m needing to script VLC to automate some of the manual processes. As part of this process, the user is presented a dialog to choose a folder of movies to play. That all works fine. However, I haven’t found a way from the dictionary to clear the playlist each time a new folder of movies is picked. The only two ways I know of, so far, is to quit VLC or choose “Select All” and then “Clear” from the edit menu. Do you know of another way to clear the playlist in VLC?

Thanks!

1 Like

Bill,

UI Browser worked like a champ…thanks for the referral! Going to buy it later today. The VLC scripting seems to work well now, so we’re off an running.

Thanks!

1 Like