Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Ipodize

macrumors member
Original poster
I'd like to make a simple AppleScript (or XCode, doesn't really matter as long as i can compile it into a Mac application) utility that connects to a WPA network automatically for me. Anyone have any ideas as to how it could work? I've tried some stuff from this page: http://hints.macworld.com/article.php?story=20060921045743404 but can't figure out how to find the name of the wifi menu bar item. If you have any ideas as to how i could do it a different way, please let me know. Thanks!
 
I'd like to make a simple AppleScript (or XCode, doesn't really matter as long as i can compile it into a Mac application) utility that connects to a WPA network automatically for me. Anyone have any ideas as to how it could work? I've tried some stuff from this page: http://hints.macworld.com/article.php?story=20060921045743404 but can't figure out how to find the name of the wifi menu bar item. If you have any ideas as to how i could do it a different way, please let me know. Thanks!

To find out the name of the menu items, you need a tool called UIElementInspector, or the newer Accessibility Inspector, which can be found here:

/Developer/Applications/Utilities/Accessibility Tools/Accessibility Inspector.app

... if you have the latest developer tools installed. I can't find a simple download link of UIElementInspector, but its available as sample code to compile yourself, which again would require developer tools installed.

These tools display the names of all the menus, menu items, buttons, etc to let you write UI Applescripts. You just mouse over a UI element anywhere on the screen and it shows you all the details in a window.

I don't have wireless on this mac, so can't get the names of the menu for you.

I've done one for Bluetooth which works for me here on Snow Leopard 10.6.6:

Code:
tell application "System Events"
   tell process "SystemUIServer"
      tell menu bar 1
         set menuExtras to (value of attribute "AXChildren")
         tell menuExtras
            set bluetooth to (first item whose (value of attribute "AXDescription") contains "bluetooth")
         end tell
         tell bluetooth
            perform action "AXPress"
            tell menu 1
               if name of menu item 1 ends with "Off" then
                  click menu item "Turn Bluetooth On"
               else
                  -- just close the menu if Bluetooth is already on
                  tell bluetooth to perform action "AXPress"
               end if
            end tell
         end tell
         
      end tell
   end tell
end tell
Which is taken from coolsoldier's post here:
http://hints.macworld.com/article.php?story=20060921045743404

Edit:
Ok, tried this on an iBook with 10.4.11 Tiger and it works to turn Airport on. Selecting a network would require you to know the name of it and I'll leave that up to you.
Code:
tell application "System Events"
   tell process "SystemUIServer"
      tell menu bar 1
         set menuExtras to (value of attribute "AXChildren")
         set airport to -1
         repeat with aMenu in menuExtras
            tell aMenu
               if value of attribute "AXDescription" contains "AirPort Menu Extra" then
                  set airport to aMenu
                  exit repeat
               end if
            end tell
         end repeat
         
         if airport is -1 then
            display dialog "Could not find AirPort Menu Extra"
         else
            tell airport
               perform action "AXPress"
               tell menu 1
                  if name of menu item 1 ends with "Off" then
                     click menu item "Turn Airport On"
                  else
                     -- just close the menu if airport is already on
                     tell airport to perform action "AXPress"
                  end if
               end tell
            end tell
         end if
      end tell
   end tell
end tell
 
Last edited:
To find out the name of the menu items, you need a tool called UIElementInspector, or the newer Accessibility Inspector, which can be found here:

/Developer/Applications/Utilities/Accessibility Tools/Accessibility Inspector.app

... if you have the latest developer tools installed. I can't find a simple download link of UIElementInspector, but its available as sample code to compile yourself, which again would require developer tools installed.

These tools display the names of all the menus, menu items, buttons, etc to let you write UI Applescripts. You just mouse over a UI element anywhere on the screen and it shows you all the details in a window.

I don't have wireless on this mac, so can't get the names of the menu for you.

I've done one for Bluetooth which works for me here on Snow Leopard 10.6.6:

Code:
tell application "System Events"
   tell process "SystemUIServer"
      tell menu bar 1
         set menuExtras to (value of attribute "AXChildren")
         tell menuExtras
            set bluetooth to (first item whose (value of attribute "AXDescription") contains "bluetooth")
         end tell
         tell bluetooth
            perform action "AXPress"
            tell menu 1
               if name of menu item 1 ends with "Off" then
                  click menu item "Turn Bluetooth On"
               else
                  -- just close the menu if Bluetooth is already on
                  tell bluetooth to perform action "AXPress"
               end if
            end tell
         end tell
         
      end tell
   end tell
end tell
Which is taken from coolsoldier's post here:
http://hints.macworld.com/article.php?story=20060921045743404

Edit:
Ok, tried this on an iBook with 10.4.11 Tiger and it works to turn Airport on. Selecting a network would require you to know the name of it and I'll leave that up to you.
Code:
tell application "System Events"
   tell process "SystemUIServer"
      tell menu bar 1
         set menuExtras to (value of attribute "AXChildren")
         set airport to -1
         repeat with aMenu in menuExtras
            tell aMenu
               if value of attribute "AXDescription" contains "AirPort Menu Extra" then
                  set airport to aMenu
                  exit repeat
               end if
            end tell
         end repeat
         
         if airport is -1 then
            display dialog "Could not find AirPort Menu Extra"
         else
            tell airport
               perform action "AXPress"
               tell menu 1
                  if name of menu item 1 ends with "Off" then
                     click menu item "Turn Airport On"
                  else
                     -- just close the menu if airport is already on
                     tell airport to perform action "AXPress"
                  end if
               end tell
            end tell
         end if
      end tell
   end tell
end tell

Thanks! I do have developer tools installed, and this script works fine, with a small modification (I'm on 10.5.8, and the first menu item for me is airport's status, eg. "Airport Off", and isn't clickable. To turn airport on, you need to click the item below which, if Airport is off, is "Turn Airport On" and, if Airport is on, is "Turn Airport Off".) To get the script to work i just modified this:

Code:
if name of menu item 1 ends with "Off" then
click menu item "Turn Airport On"

into this:

Code:
if name of menu item 2 ends with "On" then
click menu item "Turn Airport On"

The thing is, because the network I'd like to connect to has a hidden SSID, the network doesn't display on the list (even though I've already connected to it a quintillion times, and I've clicked "Remember this network" pretty much all of those times...) so i need to re-enter the 25-character password every time i wake my mac up, which is annoying. What i'd need to do in Applescript is select the "Join Other Network..." menu item (which for some reason doesn't work with the code " click menu item "Join Other Network" ", here's the Accessibility Inspector output from hovering over it:

Code:
<AXApplication: “SystemUIServer”>
 <AXMenuBar>

Attributes:
   AXRole:  “AXMenuBar”
   AXRoleDescription:  “menu bar”
   AXChildren:  “<array of size 2>”
   AXParent:  “<AXApplication: “SystemUIServer”>”
   AXEnabled:  “true”
   AXPosition:  “x=0 y=0”
   AXSize:  “w=1440 h=22”
   AXSelectedChildren (W):  “<array of size 0>”
   AXVisibleChildren:  “<array of size 2>”
   AXTitleUIElement:  “(null)”

Actions:
   AXCancel - cancel


,i posted a screenshot of the error below), then enter the SSID, then select "WPA Personal" in the dropdown menu, then select the password field, then enter the password, then press OK... which could get a bit difficult for an Applescript newbie like me :rolleyes:

I'll see if i can get it to work. Thanks again for your effort!
 

Attachments

  • Picture 7.png
    Picture 7.png
    36.4 KB · Views: 6,070
  • Picture 5.png
    Picture 5.png
    51 KB · Views: 282
  • Picture 8.png
    Picture 8.png
    39.7 KB · Views: 260
Last edited:
Thanks! I do have developer tools installed, and this script works fine, with a small modification (I'm on 10.5.8, and the first menu item for me is airport's status, eg. "Airport Off", and isn't clickable. To turn airport on, you need to click the item below which, if Airport is off, is "Turn Airport On" and, if Airport is on, is "Turn Airport Off".) To get the script to work i just modified this:

Code:
if name of menu item 1 ends with "Off" then
click menu item "Turn Airport On"

into this:

Code:
if name of menu item 2 ends with "On" then
click menu item "Turn Airport On"

If that works for you then that's all that matters. Did you try it first? The first one checks for the status in the first non-selectable menu item "Airport Off", it doesn't try to click it. Your one checks for the "On" at the end of "Turn Airport On", which should work too.

The thing is, because the network I'd like to connect to has a hidden SSID, the network doesn't display on the list (even though I've already connected to it a quintillion times, and I've clicked "Remember this network" pretty much all of those times...) so i need to re-enter the 25-character password every time i wake my mac up, which is annoying. What i'd need to do in Applescript is select the "Join Other Network..." menu item (which for some reason doesn't work with the code " click menu item "Join Other Network" ", here's the Accessibility Inspector output from hovering over it:
Notice the difference between the menu item name and your applescript command. You have to type those full stops at the end so it matches exactly.

,i posted a screenshot of the error below), then enter the SSID, then select "WPA Personal" in the dropdown menu, then select the password field, then enter the password, then press OK... which could get a bit difficult for an Applescript newbie like me :rolleyes:

Applescript can be a pain, especially UI scripting where the names, positions and types of the elements changes with different versions of OS X. It seems like we're in different time zones, so this is going a bit slowly.
 
The thing is, because the network I'd like to connect to has a hidden SSID, the network doesn't display on the list

If it's your wireless network, then give it a non-empty SSID.

The network isn't any more secure for being nameless. Attackers can still see it, and still attack it using the BSSID:
http://en.wikipedia.org/wiki/Service_set_(802.11_network)#Security_gains_of_SSID_hiding
"Unfortunately, turning off the broadcast of the SSID may lead to a false sense of security. The method discourages only casual wireless snooping, but does not stop a person trying to attack the network."​
 
Here's the problem:

click menu item "Join Other Network"

Should be:

click menu item "Join Other Network..."

BUT that's not three full stops, it's an ellipsis character, ONE character.
Unfortunately, I'm on my phone just now so can't type it in. I'll try later.

That was what I noticed on 10.4 where the menu item was "Other..."
 
If that works for you then that's all that matters. Did you try it first? The first one checks for the status in the first non-selectable menu item "Airport Off", it doesn't try to click it. Your one checks for the "On" at the end of "Turn Airport On", which should work too.

Notice the difference between the menu item name and your applescript command. You have to type those full stops at the end so it matches exactly.

Applescript can be a pain, especially UI scripting where the names, positions and types of the elements changes with different versions of OS X. It seems like we're in different time zones, so this is going a bit slowly.

I'm in Australia, so yes, we are in different time zones.

If it's your wireless network, then give it a non-empty SSID.

The network isn't any more secure for being nameless. Attackers can still see it, and still attack it using the BSSID:
http://en.wikipedia.org/wiki/Service_set_(802.11_network)#Security_gains_of_SSID_hiding
"Unfortunately, turning off the broadcast of the SSID may lead to a false sense of security. The method discourages only casual wireless snooping, but does not stop a person trying to attack the network."​

The network isn't mine, I talked to the owner but he reasons that, as far as he knows, no one would bother to launch a proper attack on the network ( it's just a home network ) and the only people who know about the networks existence are friends and family who have no idea how to connect to a network, let alone hack one ;)

I'm not sure if I entirely accept that reasoning, but it isn't my network, so that's the end of it (according to the network owner)

Here's the problem:

click menu item "Join Other Network"

Should be:

click menu item "Join Other Network..."

BUT that's not three full stops, it's an ellipsis character, ONE character.
Unfortunately, I'm on my phone just now so can't type it in. I'll try later.

That was what I noticed on 10.4 where the menu item was "Other..."

That makes sense! I'd already tried adding three full stops, but it didn't work. Here's some updated code that clicks on "Join Other Network…" and types in the SSID:
Code:
tell application "System Events"
	tell process "SystemUIServer"
		tell menu bar 1
			set menuExtras to (value of attribute "AXChildren")
			set airport to -1
			repeat with aMenu in menuExtras
				tell aMenu
					if value of attribute "AXDescription" contains "AirPort Menu Extra" then
						set airport to aMenu
						exit repeat
					end if
				end tell
			end repeat
			
			if airport is -1 then
				display dialog "Could not find AirPort Menu Extra"
			else
				tell airport
					perform action "AXPress"
					tell menu 1
						if name of menu item 2 ends with "On" then
							click menu item "Turn Airport On"
						else
							-- just close the menu if airport is already on
							click menu item "Join Other Network…"
							keystroke "SSID"
						end if
					end tell
				end tell
			end if
		end tell
	end tell
end tell
Now I just need to select "WPA Personal" in the dropdown and then enter the password (which is just as easy as entering the SSID, as after I select WPA Personal, the password box automatically gets focused) and press the "Join" button, and its done! I'll post the Accessibility Inspector output in a seperate post (for some reason it cuts off the last bit if i try and put it in this post), but I've put a screenshot of the dialog in this post.

The Accessibility Inspector output from hovering over the "Security" dropdown:

Code:
<AXApplication: “SystemUIServer”>
 <AXWindow>
  <AXPopUpButton: “None”>
Attributes:
   AXRole:  “AXPopUpButton”
   AXRoleDescription:  “pop up button”
   AXHelp:  “(null)”
   AXEnabled:  “true”
   AXFocused (W):  “false”
   AXParent:  “<AXWindow>”
   AXWindow:  “<AXWindow>”
   AXTopLevelUIElement:  “<AXWindow>”
   AXPosition:  “x=893 y=338”
   AXSize:  “w=240 h=26”
   AXValue:  “None”
   AXChildren:  “<array of size 0>”
Actions:
   AXShowMenu - show menu
   AXPress - press

and from hovering over the dropdown menu item "WPA Personal":

Code:
<AXApplication: “SystemUIServer”>
 <AXWindow>
  <AXPopUpButton: “None”>
   <AXMenu>
    <AXMenuItem: “WPA Personal”>

Attributes:
   AXRole:  “AXMenuItem”
   AXRoleDescription:  “menu item”
   AXParent:  “<AXMenu>”
   AXEnabled:  “true”
   AXPosition:  “x=666 y=417”
   AXSize:  “w=240 h=18”
   AXTitle:  “WPA Personal”
   AXHelp:  “(null)”
   AXSelected (W):  “true”
   AXMenuItemCmdChar:  “(null)”
   AXMenuItemCmdVirtualKey:  “(null)”
   AXMenuItemCmdGlyph:  “(null)”
   AXMenuItemCmdModifiers:  “0”
   AXMenuItemMarkChar:  “”
   AXMenuItemPrimaryUIElement:  “(null)”

Actions:
   AXCancel - cancel
   AXPress - press
 

Attachments

  • Picture 10.png
    Picture 10.png
    55.1 KB · Views: 266
Last edited by a moderator:
Try this:
Code:
tell application "System Events"
   tell process "SystemUIServer"
      tell menu bar 1
         set menuExtras to (value of attribute "AXChildren")
         set airport to -1
         repeat with aMenu in menuExtras
            tell aMenu
               if value of attribute "AXDescription" contains "AirPort Menu Extra" then
                  set airport to aMenu
                  exit repeat
               end if
            end tell
         end repeat
         
         if airport is -1 then
            display dialog "Could not find Menu Extra"
            return
         else
            tell airport
               perform action "AXPress"
               tell menu 1
                  click menu item "Join Other Network…"
               end tell
            end tell
         end if
      end tell
      tell window 1
         delay 0.5 -- wait for dialog to open
         keystroke "SSID"
         
         tell pop up button 1
            click
            click menu item "WPA Personal" of menu 1
            delay 0.5 -- wait for password field to appear
            keystroke tab
            keystroke tab
            keystroke "TopSecretPassword"
         end tell
         click button "Join"
      end tell
   end tell
end tell

This worked for me on an iBook with 10.4, with the only change being "Other…" instead of "Join Other Network…" and "OK" instead of "Join" for your 10.5 version.

The UI scripts often need you to click to open a menu, then maybe a delay, before they "see" that the menu items exist. The dialog needs to appear before the applescript can "see" it.

If you're on a faster mac, you can reduce the delays a bit.

I don't see any harm in turning off broadcast of SSID. I do it on my wireless network, even though I know it won't stop someone who is determined to find it out. The same with restricting MAC addresses of machines that can connect. It won't stop a determined attacker who can listen in to the MAC addresses being broadcast and spoof it. Most casual users won't be able to do this so it might stop them having a go at the password.

I'm not relying on it as the only security, its a little bit of additional help on top of WPA2-PSK [AES].
 
Last edited:
I don't see any harm in turning off broadcast of SSID.

Maybe the absence of an SSID is contributing to the inability of the computer to remember the network. From the OP's second post:
The thing is, because the network I'd like to connect to has a hidden SSID, the network doesn't display on the list (even though I've already connected to it a quintillion times, and I've clicked "Remember this network" pretty much all of those times...) (underline added)

In other words, if the network had an SSID, the computer might correctly remember the network, the entire script that drives the UI to connect to a nameless network might never have been needed. And this whole thread would be unnecessary.
 
Maybe the absence of an SSID is contributing to the inability of the computer to remember the network. From the OP's second post:


In other words, if the network had an SSID, the computer might correctly remember the network, the entire script that drives the UI to connect to a nameless network might never have been needed. And this whole thread would be unnecessary.

Turning off broadcast of SSID doesn't stop my wife's iBook from remembering the network. On the same network, it's been the same with every phone that has been set up to connect. They've never forgotten the network. The password is usually just typed once on each device.

This thread may not be needed if the network settings On Ipodize's mac were changed to work properly.

I didn't think it was nameless, I thought it had an SSID, but that it was hidden.
 
Turning off broadcast of SSID doesn't stop my wife's iBook from remembering the network. On the same network, it's been the same with every phone that has been set up to connect. They've never forgotten the network. The password is usually just typed once on each device.

This thread may not be needed if the network settings On Ipodize's mac were changed to work properly.

I didn't think it was nameless, I thought it had an SSID, but that it was hidden.

It does have a SSID, but for some reason my Mac still won't connect. Strangely enough, my iPod touch (which I am currently using to type this post) reconnects fine. I don't get what the difference is. :confused:

Also, that script looks like it will work, but I can't be sure until I get to my Mac.

And another question, is it possible to get that password out of the keychain (as it has been stored in there, along with the SSID and everything else) for some more security? I don't mind having to type in my administrator password, it's a third shorter than the network password...

EDIT: Works perfectly! Now i just need to find a way to make it a lot harder to recover the password from the script (like the keychain idea above, or the read-only option in the editor, though i'm not sure how secure that is?) or, i can use this:
Code:
tell application "System Events"
	tell process "SystemUIServer"
		tell menu bar 1
			set menuExtras to (value of attribute "AXChildren")
			set airport to -1
			repeat with aMenu in menuExtras
				tell aMenu
					if value of attribute "AXDescription" contains "AirPort Menu Extra" then
						set airport to aMenu
						exit repeat
					end if
				end tell
			end repeat
			
			if airport is -1 then
				display dialog "Could not find AirPort Menu Extra"
			else
				tell application "System Events"
					activate
					local pass
					set pass to text returned of (display dialog "Enter your password" default answer "" with hidden answer)
				end tell
				tell airport
					perform action "AXPress"
					tell menu 1
						click menu item "Join Other Network…"
					end tell
				end tell
			end if
		end tell
		tell window 1
			delay 0.1 -- wait for dialog to open
			keystroke "SSID"
			
			tell pop up button 1
				click
				click menu item "WPA Personal" of menu 1
				delay 0.1 -- wait for password field to appear
				keystroke pass
			end tell
			click button "Join"
		end tell
	end tell
end tell
which makes it a bit easier by eliminating the mouse clicks (when used with QuickSilver) but I'd prefer to have it enter the password automatically, but still have it stored securely.
 
Last edited:
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.