Did a script to find all other Macs on network

I’ve found it annoying to write a script to interact with other Macs and have it fail because the Mac isn’t on or for whatever reason can’t be connected to. The task goes undone and I don’t know about until I hear about a problem later. So I wrote a script today that finds the Macs connected to the local network and get their host names. Then the script can check to see if the Mac is ready before before starting the script and the script can report back to me right away if the Mac isn’t responding. This can differentiate between the Mac not being on the network and the script timing out. Which usually required different actions. I still have yet to do the part that sends me a text message to my Verizon phone. But I figured this was close enough.

If anyone does care about that verizon has an email address for all its phones and if a mail message is set to it, the message is forwarded to the phone. For verizon the format is AAANNNNNN@vtext.com where AAA is the area code and NNNNNN is the rest of the number. I don’t know the format for other cell phone providers. I’ve never cared for any of the other solutions I’ve found.

If anyone is interested here is the script. I put a bunch of comments in the script:

use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

-- This script finds the other Macs that can be seen over the network from your current Mac.
-- This script finds the other Bonjour service types of the specified type that can been seen from the current Mac.
-- There is a long list of these services on https://developer.apple.com/library/content/qa/qa1312/_index.html
-- It's simpler to look at the list then me explaning Bonjour beyond that it allows services on the network to be discovered dynamicly
-- If you want to have you Mac in the the list then remove the part where it says (NetworkServiceName ≠ CurrentHostName) and

property OtherHostsList : {}
property CurrentHostName : ""
property DoneGettingServices : false

on netServiceBrowser:NotUsed1 didFindService:NetworkService moreComing:StillServicesLeft
	set DoneGettingServices to not StillServicesLeft
	set NetworkServiceName to (NetworkService's |name|()) as text
	
	-- if (NetworkServiceName ≠ my ServiceName) and (NetworkServiceName is not already in OtherHostsList list)
	if (NetworkServiceName ≠ CurrentHostName) and (NetworkServiceName is not in OtherHostsList) then
		set the end of OtherHostsList to NetworkServiceName
	end if
end netServiceBrowser:didFindService:moreComing:

set DoneGettingServices to false
set OtherHostsList to {}
-- This is the host that goes with my Mac
set CurrentHostName to (current application's NSHost's currentHost()'s localizedName()) as string

set TheServiceBrowser to current application's NSNetServiceBrowser's alloc()'s init()
TheServiceBrowser's setDelegate:me

-- _afpovertcp._tcp indicates searching for AppleTalk Filing Protocol (AFP) which is used by Personal File Sharing
-- This is opposed to _nfs._tcp which which searches Network File System (NFS) servers
-- To do the same thing, except search for servers use "_nfs._tcp" instead of "_afpovertcp._tcp"
-- This line will automtically netServiceBrowser:didFindService:moreComing: at the beginning of the script
TheServiceBrowser's searchForServicesOfType:"_afpovertcp._tcp" inDomain:""

repeat while not DoneGettingServices
	-- Need this delay or it will not work
	delay 1.0E-5
end repeat

-- Reset the delegate to unused
TheServiceBrowser's setDelegate:(missing value)

OtherHostsList

Nice script!

Note that the repeat loop is only required in SD. If you save it as an applet or run it from, say, FastScripts, you should be able to cut the repeat out and just check the moreComing: parameter in the delegate method.

Shane,

I thought it was a very useful script and it was as small and simple as I could make it. But what about it made it a “Nice script!,” or are the reasons I just mentioned why you said “Nice script!” I don’t see that very often so it surprised me.

My understanding for an applet was that program control started from the beginning of the script and just ran to the end and that was it. In apps things are event driven so events initiate actions. In this case there is still a loop but that loop is called the event loop and is handled by the system and from the apps point of view it is all event driven.

Am I misunderstanding something here? Although I could just remove the loop and see what happens in an applet. I am implementing this using compiled scripts from FastScripts and I haven’t tried an applet yet.

Bill

As you said – useful and simple.

No, it just seems like that. Save an applet as stay-only and it just sits waiting for events, or for its handlers to be called.

There’s a threading issue here, too. If you run it from the main thread in Script Editor, it should work until you save/close the script.

Shane,

In the past I used to see people that appreciate such things but I haven’t heard anyone take note of, or appreciate, simple and useful for a while. That’s how I try to make everything. It’s a lot easier to edit something short and simple 4 years after writing it then a long complex script. Not to mention there is a certain eloquence about something in its simplest and smallest form :slight_smile:

You got me on that one. If I had thought that through it would have occurred to me I didn’t need the loop in an applet. What would be the point of a “stay open” applet then ran though its code and was done after that. Now that you point it out it’s obvious the loop can go in an applet. Well I never claimed to be a smart scripter :slight_smile:

Bill

Great stuff Bill. This seems like such a basic need.

What is the minimal OS requirement for this to run?

Thanks.

It requires OS X 10.9 or later.