Can't find UI Hierarchy

Hey everyone,

I’ve spent all day researching this and I can’t find the answer. I’m trying to script an application “PdaNet.” It is a simple menu bar extension that allows me to tether my iPhone for internet sharing. I’m trying to create a script that will select the connect button from that menu but every method I’ve used to try to find the hierarchy of the menu item comes up empty.

I used element inspector to analyze the menu but the “Connect” menu item does not like to it’s parent. UI Browser gives me this:

ELEMENT PATH (FROM LEAF ELEMENT)
menu item “Connect” (menu item 1)
menu (menu -9223372036854775808)
[MISMATCH-no children] button “” (button -9223372036854775808)
[MISMATCH-no children] application “PdaNetMac”

When I view PdaNet with UI Browser, the only menu items it shows are File, Edit, View… none of which have a menu item for “Connect”. I tried this script:


tell application "PdaNetMac"
	activate
end tell
tell application "System Events"
	tell process "PdaNetMac"
		tell button -9223372036854775808
			tell menu -9223372036854775808
				tell menu item "Connect"
					click
				end tell
			end tell
		end tell
	end tell
end tell

But it really doesn’t like that number -9223372036854775808 and tells me:

“System Events got an error: Can’t make -9.22337203685478E+18 into type integer.”

And replacing that number with 1 just tells me that Applescript can’t find that button.

LOOOONGG story short, how do I script an element that doesn’t seem to be properly connected to it’s parent? How do I find this element?

Thanks!

A lot of right side menu bar apps cannot be scripted; I’ve never succeeded in scripting several of them beyond the drop down menu itself. Apparently the menu contents are often not reachable at all and the UI browser won’t see them.

No man don’t say that! What a bummer. All that work. Oh well. Thanks for the quick response.

I have exactly the same problem. The application in my case has pop up button all over the application. Without finding a solution for this issue, my automation scripts are pretty much useless. :frowning:

Has any one had any luck on this?

This issue can be found on System Preferences->Network->Wi-Fi (Airport). Menu items in Popup button “Network Name” cannot be accessed

Any help on this would be greatly appreciated

My guess it that you missed several infos given by UI Elements Inspector (I use Accessibility Inspector.app)

I downloaded PdaNetMac.app but it does nothing when I double-click it.


tell application "PdaNetMac"
	activate
end tell
tell application "System Events"
	tell process "PdaNetMac"
		properties of every window -- <<<<< added
		tell window 1 -- <<<<< added
			properties of every UI element -- <<<<< added
			tell button "-9223372036854775808" -- <<<<< edited
				tell menu "-9223372036854775808" -- <<<<< edited
					tell menu item "Connect"
						click
					end tell
				end tell
			end tell
		end tell -- <<<<< added
	end tell
end tell

As far as I know the names of buttons aren’t numbers but strings.
The added instructions would give you the needed informations.

As the app does nothing here I can’t give more infos about it so I post an example about an other app.

You will see the kind of infos returned by the added instructions :



(*
keynote_to_pdf
*)
on run
	local leFichier, pointEtExtension, dossierSource, nomDuFichier, nomFenetre, dossierParDefaut, cheminPDFtemporaire, nomCourt, nomFinal, cheminFinal
	
	set leFichier to (path to documents folder as text) & "tempo:beurk.key" as alias
	--set leFichier to (path to desktop as text) & "beurk.key" as alias
	
	set pointEtExtension to ".key"
	my activateGUIscripting()
	
	tell application "System Events" to tell disk item (leFichier as text)
		set dossierSource to path of container
		set nomDuFichier to name
	end tell -- System Events
	
	if nomDuFichier ends with pointEtExtension then
		set nomFenetre to nomDuFichier
	else
		set nomFenetre to nomDuFichier & pointEtExtension
	end if -- nomDuFichier.
	
	tell application "Keynote"
		open leFichier
		repeat until name of every slideshow contains nomFenetre
			--
		end repeat
	end tell -- Keynote
	set dossierParDefaut to my getDossierParDefaut()
	
	set cheminPDFtemporaire to dossierParDefaut & nomFenetre & ".pdf"
	
	tell application "System Events"
		if exists (disk item cheminPDFtemporaire) then set name of disk item cheminPDFtemporaire to nomFenetre & my horoDateur(modification date of file cheminPDFtemporaire) & ".PDF" (* name stamped *)
	end tell -- System Events
	
	tell application "System Events" to tell application process "Keynote"
		set frontmost to true
		keystroke "p" using command down
		tell window nomFenetre
			repeat
				try
					if description of sheet 1 is "Print" then exit repeat
				end try
			end repeat
			tell sheet 1
				-- properties of every button
				(* --> {
(1) {minimum value:missing value, orientation:missing value, position:{835, 591}, class:button, role description:"bouton", accessibility description:missing value, focused:false, title:"Imprimer", size:{98, 32}, value:missing value, help:missing value, enabled:true, maximum value:missing value, role:"AXButton", entire contents:{}, subrole:missing value, selected:missing value, name:"Imprimer", description:"bouton"}, 
(2) {minimum value:missing value, orientation:missing value, position:{737, 591}, class:button, role description:"bouton", accessibility description:missing value, focused:false, title:"Annuler", size:{98, 32}, value:missing value, help:missing value, enabled:true, maximum value:missing value, role:"AXButton", entire contents:{}, subrole:missing value, selected:missing value, name:"Annuler", description:"bouton"}, 
(3) {minimum value:missing value, orientation:missing value, position:{49, 595}, class:button, role description:"bouton", accessibility description:"Aide", focused:false, title:missing value, size:{25, 25}, value:missing value, help:missing value, enabled:true, maximum value:missing value, role:"AXButton", entire contents:{}, subrole:missing value, selected:missing value, name:missing value, description:"Aide"}}
			*)
				-- properties of every menu button
				(* --> {
(1) {minimum value:missing value, orientation:missing value, position:{81, 593}, class:menu button, role description:"bouton de menu", accessibility description:missing value, focused:false, title:"PDF", size:{85, 26}, value:missing value, help:missing value, enabled:true, maximum value:missing value, role:"AXMenuButton", entire contents:{}, subrole:missing value, selected:missing value, name:"PDF", description:"bouton de menu"}}
*)
				-- properties of every radio group
				(* --> {
(1) {minimum value:missing value, orientation:missing value, position:{389, 355}, class:radio group, role description:"groupe de radio", accessibility description:missing value, focused:false, title:missing value, size:{219, 84}, help:missing value, enabled:true, maximum value:missing value, role:"AXRadioGroup", entire contents:{}, subrole:missing value, selected:missing value, name:missing value, description:"groupe de radio"}, 
(2) {minimum value:missing value, orientation:missing value, position:{555, 257}, class:radio group, role description:"groupe de radio", accessibility description:missing value, focused:false, title:missing value, size:{65, 41}, help:missing value, enabled:true, maximum value:missing value, role:"AXRadioGroup", entire contents:{}, subrole:missing value, selected:missing value, name:missing value, description:"groupe de radio"}}
*)
				tell first radio group
					-- properties of every UI element
					(*
--> {
(1) {minimum value:missing value, orientation:missing value, position:{389, 355}, class:radio button, role description:"bouton radio", accessibility description:missing value, focused:false, title:"Diapositives individuelles", size:{219, 18}, value:0, help:missing value, enabled:true, maximum value:missing value, role:"AXRadioButton", entire contents:{}, subrole:missing value, selected:missing value, name:"Diapositives individuelles", description:"bouton radio"}, 
(2) {minimum value:missing value, orientation:missing value, position:{389, 377}, class:radio button, role description:"bouton radio", accessibility description:missing value, focused:false, title:"Diapositives avec notes", size:{219, 18}, value:1, help:missing value, enabled:true, maximum value:missing value, role:"AXRadioButton", entire contents:{}, subrole:missing value, selected:missing value, name:"Diapositives avec notes", description:"bouton radio"}, 
(3) {minimum value:missing value, orientation:missing value, position:{389, 399}, class:radio button, role description:"bouton radio", accessibility description:missing value, focused:false, title:"Structure", size:{219, 18}, value:0, help:missing value, enabled:true, maximum value:missing value, role:"AXRadioButton", entire contents:{}, subrole:missing value, selected:missing value, name:"Structure", description:"bouton radio"}, 
(4) {minimum value:missing value, orientation:missing value, position:{389, 421}, class:radio button, role description:"bouton radio", accessibility description:missing value, focused:false, title:"Document", size:{219, 18}, value:0, help:missing value, enabled:true, maximum value:missing value, role:"AXRadioButton", entire contents:{}, subrole:missing value, selected:missing value, name:"Document", description:"bouton radio"}}
				*)
					tell radio button 2 to if value is 0 then click (* Active "Diapositives avec notes" *)
				end tell -- first radio group
				click menu button 1 (* PDF *)
				-- name of every menu item of menu 1 of menu button 1
				(* --> {
"Ouvrir le PDF dans Aperçu",
"Enregistrer au format PDF.",
"Enregistrer au format PostScript.",
"Faxer le document PDF.",
missing value,
"@ PDF-BAT.qfilter",
"@ PDF-prépresse CMJN.qfilter",
"@ PDF-web.qfilter",
"@ PDFX3-ISO.qfilter",
"Envoyer le document PDF par courrier électronique",
"Enregistrer en PDF-X",
"Enregistrer le document PDF vers iPhoto",
"Enregistrer le document PDF dans le dossier de reçus Web",
missing value,
"Modifier le menu."
} *)
				click menu item 2 of menu 1 of menu button 1 (* click item Save as PDF. *)
				keystroke return (* idem click OK *)
			end tell -- sheet 1
		end tell -- window.	
	end tell -- System Events.
	
	if nomDuFichier ends with pointEtExtension then
		set nomCourt to text 1 thru -(1 + (count of pointEtExtension)) of nomDuFichier
	else
		set nomCourt to nomDuFichier
	end if
	set nomFinal to nomCourt & ".pdf"
	
	set cheminFinal to dossierSource & nomFinal
	tell application "System Events"
		repeat until exists disk item cheminPDFtemporaire
			delay 1
		end repeat -- System Events
		if exists (disk item cheminFinal) then set name of disk item cheminFinal to nomCourt & my horoDateur(modification date of file cheminFinal) & ".PDF" (* name stamped *)
	end tell
	
	if dossierSource is dossierParDefaut then
		tell application "System Events"
			set name of disk item cheminPDFtemporaire to nomFinal
		end tell -- System Events
	else
		do shell script "mv " & (quoted form of POSIX path of cheminPDFtemporaire) & " " & quoted form of POSIX path of cheminFinal
	end if -- dossierSource.
	
	tell application "Keynote" to quit
end run

--=====
(* Build a stamp from the modification date_time
*)
on horoDateur(une_date)
	tell une_date to return "_" & (((its year) * 10000 + (its month) * 100 + (its day)) as text) & "_" & text 2 thru -1 of ((1000000 + (its hours) * 10000 + (its minutes) * 100 + (its seconds)) as text)
	(* 
¢ Here, the stamp is  "_YYYYMMDD_hhmmss" *)
end horoDateur

--=====

on getPlistValue(valName, default)
	local thePlist, u
	set thePlist to (path to preferences folder as Unicode text) & "com.apple.iWork.Keynote.plist"
	tell application "System Events"
		if exists file thePlist then
			tell contents of property list file thePlist
				try
					set u to (value of property list item valName) (* Unicode Text *)
				on error (*
On est là si AppleWorks n'a rien enregistré avec des préférences neuves
¢ Here if AppleWorks never saved with the new preferences file. *)
					set u to default
				end try
			end tell -- to contents of.
		else (*
On est là s'il n'y a pas de fichier de préférences
¢ Here if there is no preferences file. *)
			set u to default
		end if
	end tell -- to system events
	return u
end getPlistValue

--=====

on getDossierParDefaut()
	local u
	try
		set u to my getPlistValue("NSNavLastRootDirectory", "~/Documents")
		set u to "" & POSIX file (do shell script "echo " & u)
		if u ends with ":" then
			return u
		else
			return (u & ":")
		end if
	on error
		return ("" & (path to documents folder))
	end try
end getDossierParDefaut

--=====

on activateGUIscripting()
	(* to be sure than GUI scripting will be active *)
	tell application "System Events"
		if not (UI elements enabled) then set (UI elements enabled) to true
	end tell
end activateGUIscripting

--=====


Yvan KOENIG (VALLAURIS, France) mercredi 21 septembre 2011 12:46:21