help please: wait for window to be active

I’m currently writing a script to automate running the installation of an application.
Its a simple script, simply clicking the continue or next button.

What i need is a way for applescript to figure out that the continue button or window i’m referring to actually exists before clicking it.

I’m currently using delays but sometimes the window loads longer or faster than expected:

click button “Continue” of sheet 1 of window 1
delay 0.5
click button “Continue” of window 1
delay 0.5
click button “Continue” of window 1

etc…

I’m sure you guys can get the picture.

when using AutoIt for windows, the syntax is WinWaitActive. I hope there’s something for AppleScript.

Hi,

I’m always using this way for an appearing UI element


	repeat until exists [unique UI element]
		delay 0.2
	end repeat

or for disappearing UI element


	repeat while exists [unique UI element]
		delay 0.2
	end repeat

Thanks, now that part worked.
New problem, i tried adding it as a handler so that i can reuse it but it doesnt seem to work. here’s my code:

it returns the error "System Events got an error: Can’t get button “Install” of sheet 1 of window 1 of process “Installer”. (-1728)


on winWaitActive(objectID)
	repeat until exists objectID
		delay 0.2
	end repeat
end winWaitActive

on clicked theObject
	tell application "System Events"
		tell process "Installer"
			my winWaitActive("button \"Continue\" of sheet 1 of window 1")
			click button "Continue" of sheet 1 of window 1
		end tell
	end tell
end if

i also tried this:
winWaitActive(“button "Continue" of sheet 1 of window 1”) of me

help would be very much appreciated.

First of all you must add a System Events tell block in the handler, because the parameter contains System Events terminology. Second of all pass the reference of the UI elements, not a literal string


on winWaitActive(objectID)
	tell application "System Events"
		repeat until exists objectID
			delay 0.2
		end repeat
	end tell
end winWaitActive

on clicked theObject
	tell application "System Events"
		tell process "Installer"
			set buttonContinue to a reference to button "Continue" of sheet 1 of window 1
			my winWaitActive(buttonContinue)
			click buttonContinue
		end tell
	end tell
end clicked

I decided to add the application name and the process name as a variable. How do I do this?
Currently I’m using the code below, which won’t build successfully:


on winWaitActive(theAppName, theProcName, theObjectID)
	
	tell application theAppName
		tell process theProcName
			
			repeat until exists theObjectID
				delay 0.2
			end repeat
			click theObjectID
			
		end tell
	end tell
	
end winWaitActive

I also noticed that:
set buttonControl to a reference to button “Continue” of sheet 1 of window 1

causes a build to fail.

Is there another way to declare this? I cannot find any resources on the net about this.

Thanks

tell application [variable]

doesn’t work. The application must be specified by a literal string to be able to resolve the terminology at compile time.
In your case it’s not necessary anyway, because process is a part of System Events

Thanks so much StefanK.

How about the line:


set buttonContinue to a reference to button "Continue" of sheet 1 of window 1

Is it the correct syntax? It causes the build to fail.

try it without a reference to

still won’t work. Is there some special way of declaring a “button x of sheet 1 of window 1” ?
I’m new to applescript and i cannot find any references about this online.

thanks

There must be another cause.
The syntax is correct (even with the a reference to) if the line is within a System Events tell block

Thanks so much stefank. I finally got the handler declaration and calling to work.

I made some alterations to the code:


on ButtonClick(theObjectID)
	
	tell application "System Events"
		repeat until exists theObjectID
			delay 0.2
		end repeat
		click theObjectID
	end tell
	
end ButtonClick

tell application "System Events"
	tell process "Installer"
                my ButtonClick("Installer", button "Continue" of window 1)
		keystroke "password"
		keystroke return
		my ButtonClick("Installer", button "Close" of window 1)
				
	end tell
end tell

Problem now is that the part with the repeat until doesn’t seem to work anymore.
Before I placed the repeat clause in a handler, it worked perfectly, now, it seems to just move to the next line imediately giving me an error that goes something like "Cannot find button “Close”… if there is a slight delay in displaying the button.

What is the difference? The buttons click properly so I doubt it is the declaration.

Another problem i noticed is that there is a few seconds delay before the keystroke command is sent which delays the entering of the password into the form.

Please help.

You’re passing two parameters to the handler but in the handler declaration there’s only one.
I noticed also that there is a delay before accepting username and password in an authentication window.
It seems to be “normal”

sorry, i made a mistake in posting the script. it should have been the following:


on ButtonClick(theObjectID)
   
   tell application "System Events"
       repeat until exists theObjectID
           delay 0.2
       end repeat
       click theObjectID
   end tell
   
end ButtonClick

tell application "System Events"
   tell process "Installer"
       my ButtonClick(button "Continue" of window 1)
       keystroke "password"
       keystroke return
      my ButtonClick(button "Close" of window 1)
               
   end tell
end tell

There’s only one parameter in the actual code.

So there really is an expected delay when you enter the password into the authentication dialog? I think its a bit long (prbably around 5 seconds)

the UI elements inherit from the process, so include the process in the handler


on ButtonClick(theObjectID)
	tell application "System Events"
		tell process "Installer"
			repeat until exists theObjectID
				delay 0.2
			end repeat
			click theObjectID
		end tell
	end tell
end ButtonClick

tell application "System Events"
	
	my ButtonClick(button "Continue" of window 1)
	keystroke "password"
	keystroke return
	my ButtonClick(button "Close" of window 1)
	
end tell


Rather than scripting keystrokes try to insert the text directly into the text field

Done that, I used new handler used is below:


on ButtonClick(theProcess, theObjectID)
	
	tell application "System Events"
		tell process "Installer"
			repeat until exists theObjectID
				delay 0.2
			end repeat
			click theObjectID
		end tell
	end tell
end ButtonClick

\

error message i get is:

System Events got an error: Can’t get button “Close” of window 1 of process “Installer”. (-1728)

i’ve been stuck with this since last week.
Thanks for being so accomodating.

Probably the UI reference is wrong.
Download UIEelementinspector, the sample code includes also the application

the reference is correct. If i proceed to the window and use

click button “Close” of window 1

it works. The problem only occurs if for the repeat clause.

I’ve tested this script with an installer using Installer.app, it works


on ButtonClick(theObjectID)
	tell application "System Events"
		repeat until exists theObjectID
			delay 0.2
		end repeat
		click theObjectID
	end tell
end ButtonClick

tell application "System Events"
	tell process "Installer"
		my ButtonClick(button "Continue" of window 1)
		-- keystroke "password"
		-- keystroke return
		my ButtonClick(button "Go Back" of window 1)
	end tell


I’m having difficult making this happen. I too am trying to make a WinWaitActive-like functionality from AHK or AutoIt. It blows past it every time though.

Here’s what I have.


property Helpers : load script POSIX file "helpers.scpt" -- load helper file

tell Helpers
	activate_finale()
	menu_click_finale({"Utilities", "Change", "Ties."})
	win_wait_active("Change Note Durations")
end tell

display dialog "Was it right?"

Here is the relevant section of the helper file for win_wait_active (stolen and edited above):


on win_wait_active(theObjectID)
	tell application "System Events"
		repeat until exists theObjectID
			delay 0.2
		end repeat
	end tell
end win_wait_active

I intentionally set it up to fail by opening up the WRONG window (I tell it to open “Change Ties”). When “Change Ties” opens up I tell it to wait for “Change Note Durations” to show up to see if it will wait before executing the dialog. Since “Change Note Durations” is never going to show up, I should never see the dialog, but instead it immediately goes to the dialog every time as if the win_wait_active wasn’t even there.

I’m a applescript noob, so I bet it’s pretty simple.

Thanks in advance.

I tried the code straight forward in Finale 2014


property finaleProcess : "Finale 2014"

activate application finaleProcess
tell application "System Events"
	tell process finaleProcess
		click menu item "Ties." of menu 1 of menu item "Change" of menu 1 of menu bar item "Utilities" of menu bar 1
		repeat until exists window "Change Ties"
			delay 0.2
		end repeat
	end tell
end tell

you pass a literal string to the handler win_wait_active() but it’s supposed to be a reference to a window.
Try this, the reference must also include the process

property finaleProcess : "Finale 2014"

on win_wait_active(theObjectID)
	tell application "System Events"
		repeat until exists window theObjectID of process finaleProcess
			delay 0.2
		end repeat
	end tell
end win_wait_active