thanks Hank, I’m using the original property names from the documentation,
I’ll look for a solution to avoid that terminology clash
No problem and thanks for the tool.
One more question. Is there a way to scan for any service type rather than specifying one? Maybe it’s an easy update? In general I’d like to know any available service on my network and would prefer not to loop through all of them… I found a complete list here.
Of course it’s possible (see Bonjour Browser), but it’s quite expensive,
because you have to instantiate one browser instance for each type, there is no “searchAll” or “searchInList” method.
Resolving the terminology clash I changed the command
scan type to scan for type
and the property of service
type to service type
the keyword type is internally used in AppleScript, probably that caused the problem
Version 1.3, same link
Your 2 changes worked. Your suggestion about the possible problem with “type” makes sense. Thanks for the upgrades. You’ve got a nice tool here.
Finally I discovered how to implement an callback event handler (the Cocoa Scripting documentation is very misty regarding this issue), so you can use Bonjour Events asynchronously.
This option can be enabled by using the (optional) parameter target passing the reference to a script (usually me) and implementing the did detect services event handler
using terms from application "Bonjour Events"
on did detect services serviceList for type forType with result replyResult
set {scan error:scanError, timed out:timedOut, number of services:numberOfServices} to replyResult
if scanError is not missing value then
display dialog "do some error handling"
else if timedOut then
display dialog "event timed out"
else if numberOfServices > 0 then
display dialog "Number of Services: " & numberOfServices
repeat with aService in serviceList
tell aService
set serviceName to its name
set ipv4Address to IPv4 address
set theHost to host
set theType to service type
end tell
display dialog "Name: " & serviceName & return & "Host: " & theHost & return ¬
& "IPV4 Address: " & ipv4Address & return & "Type: " & theType
end repeat
end if
end did detect services
end using terms from
tell application "Bonjour Events"
scan for type "_afpovertcp._tcp" in domain "local" time out after 5.0 target me
end tell
Version 1.4, same link as in the first posting
[ANN] Version 2 of Bonjour Events
the main new feature is the ability to create multiple browsers.
The (arbitrary) name property has to be specified in the make new line, the other properties service type, domain and time out can be set in separate lines or in the scan command.
Default value for domain is an empty string (any domain). To search in the local network, pass “local”.
Default value for time out is 5 (seconds).
The service type must be a Bonjour type string like _afpovertcp._tcp.
The synchronous version returns a record:
scan error : missing value or the error reason (text)
timed out : like gave up in display dialog (boolean)
bonjour services : a list of the service instances or missing value if an error occurs
Sample code:
tell application "Bonjour Events"
-- create new browser instance, the name property is mandatory
set AFPBrowser to make new browser with properties {name:"MyBrowser"}
tell AFPBrowser
scan for type "_afpovertcp._tcp." in domain "local" time out after 10.0 -- default time out value is 5.0
end tell
(*
alternatively set the properties in separate lines
tell AFPBrowser
set domain to "local" -- default is "" (any domain)
set service type to "_afpovertcp._tcp"
scan
end tell
*)
set {scan error:scanError, timed out:timedOut, bonjour services:bonjourServices} to result
if scanError is not missing value then
-- do some error handling
else if timedOut then
-- handle time out
else if (count bonjourServices) > 0 then
set firstService to item 1 of bonjourServices
tell firstService
set ipv4Address to IPv4 address
set theHost to host
end tell
end if
-- Bonjour Events quits automatically after 5 minutes of inactivity
end tell
The asynchronous version provides two event handlers
on did appear services of browser aBrowser with result replyResult
on did disappear services of browser aBrowser hosts hostNames
The former returns the browser instance in the direct parameter aBrowser and the same record type as in the synchronous version in the replyResult parameter.
The latter returns the browser instance in the direct parameter aBrowser and a list of the disappeared host names (text) in the hostNames parameter.
To use the asynchronous version add the target parameter in the scan command with the value me.
Sample code:
using terms from application "Bonjour Events"
on did appear services of browser aBrowser with result replyResult
set {scan error:scanError, timed out:timedOut, bonjour services:serviceList} to replyResult
set numberOfServices to (count serviceList)
if scanError is not missing value then
display dialog "do some error handling"
else if timedOut then
display dialog "event timed out"
else if numberOfServices > 0 then
display dialog (numberOfServices as text) & " services in browser " & name of aBrowser & " appeared"
repeat with aService in serviceList
tell aService
set serviceName to its name
set ipv4Address to IPv4 address
set theHost to host
set theType to service type
end tell
display dialog "Name: " & serviceName & return & "Host: " & theHost & return ¬
& "IPV4 Address: " & ipv4Address & return & "Type: " & theType
end repeat
end if
end did appear services of browser
on did disappear services of browser aBrowser hosts hostNames
set numberOfHosts to (count hostNames)
if numberOfHosts > 0 then
display dialog (numberOfHosts as text) & " services in browser " & name of aBrowser & " disappeared"
repeat with aHost in hostNames
display dialog "Name: " & aHost
end repeat
end if
end did disappear services of browser
end using terms from
set bonjourType to "_afpovertcp._tcp"
tell application "Bonjour Events"
-- create new browser instance, the name property is mandatory
set AFPBrowser to make new browser with properties {name:"MyBrowser"}
tell AFPBrowser
scan for type bonjourType in domain "local" target me
end tell
end tell
Note : Bonjour Events quits automatically after 5 minutes of inactivity in the synchronous version.
In the asynchronous version the quit delay property is set to 0 (infinite) when a browser starts scanning.
You can stop a browser in one of the event handlers in code with
if name of aBrowser is "MyBrowser" then tell aBrowser to stop
At the moment all browsers are stopped the quit delay property is reset to 300 (5 minutes)
You could also stop a browser from another script file
tell application "Bonjour Events"
if exists browser "MyBrowser" then
tell browser "MyBrowser" to stop
end if
end tell
As long as Bonjour Events is running the created browser instances stay alive and send Apple Events until the application quits or the respective browser stops.
Download : Bonjour Events 2
Update: for consistency I changed the event handler definitions to
on did appear services serviceList of browser aBrowser with result replyResult
on did disappear services hostNames of browser aBrowser
extended sample code of the asynchronous version
using terms from application "Bonjour Events"
on did appear services serviceList of browser aBrowser with result replyResult
set {scan error:scanError, timed out:timedOut} to replyResult
if scanError is not missing value then
display dialog "do some error handling"
else if timedOut then
display dialog "event timed out"
else if (count serviceList) > 0 then
my notifyAppearedServices(aBrowser, serviceList)
end if
end did appear services
on did disappear services hostNames of browser aBrowser
set numberOfHosts to (count hostNames)
if numberOfHosts > 0 then
display dialog (numberOfHosts as text) & " services in browser " & name of aBrowser & " disappeared"
repeat with aHost in hostNames
display dialog "Name: " & aHost
end repeat
end if
end did disappear services
end using terms from
set bonjourType to "_afpovertcp._tcp"
tell application "Bonjour Events"
-- create new browser instance, the name property is mandatory
if (exists browser "MyBrowser") then
set AFPBrowser to browser "MyBrowser"
else
set AFPBrowser to make new browser with properties {name:"MyBrowser"}
end if
tell AFPBrowser
if is scanning then
set availableServices to services
my notifyAppearedServices(it, availableServices)
else
scan for type bonjourType in domain "local" target me
end if
end tell
end tell
on notifyAppearedServices(theBrowser, theServices)
tell application "Bonjour Events"
display dialog ((count theServices) as text) & " services in browser " & name of theBrowser & " appeared"
repeat with aService in theServices
tell aService
set serviceName to its name
set ipv4Address to IPv4 address
set theHost to host
set theType to service type
end tell
display dialog "Name: " & serviceName & return & "Host: " & theHost & return ¬
& "IPV4 Address: " & ipv4Address & return & "Type: " & theType
end repeat
end tell
end notifyAppearedServices
Download Version 2.1 (same link) : Bonjour Events 2.1
I can’t remember why I removed the archive from the server. I restored it, see the link in one of the previous posts. But I don’t know whether it’s still working or not. The creation date of the archive is 2014.
StefanK,
I can’t get your script above to compile
I got
Applescript Compile Error
Expected “given”, “into”, “with”, “without” or other parameter name but found identifier.
The error was on the second line…
on did appear services serviceList of browser aBrowser with result replyResult
@StefanK - Thank you for releasing the archive. Unfortunately, my script gives an error message with the Bonjour Events 2
version, while the original version works perfectly. I’ll keep trying to see if there’s a change in the syntax. Otherwise, I may post my script in the hope that you can see in a moment what’s going wrong. Thank you again.
How do I get 2.1?
When I click the download link above I seem to get version 2
Happy New Year and sorry for the inconvenience.
I recompiled the project against the latest SDK for Intel and Apple Silicon and code signed and notarized the app.
The minimum system version is macOS 10.15 Catalina.
To avoid further confusion the version of the app is 2.1
I ran also successfully some test scripts.
@StefanK - Thank you for compiling the latest version. I’m sorry to ask your help, but I can’t figure out how to change a script that worked with version 1 so that it works with the current version. The bit of script that used to work is this:
try
tell application "Bonjour Events"
scan type "_ipp._tcp" in domain "local"
repeat until browser finished
delay 0.5
end repeat
if (count services) > 0 then
set nameList to name of services
set addressList to IPv4 address of services
else
set nameList to {}
set addressList to {}
end if
quit
-- Bonjour Events quits automatically after 2 minutes of inactivity
end tell
on error errorMessage number errorNumber
display dialog "An error occurred: " & errorMessage & " (" & errorNumber & ")"
end try
I’ve tried changing scan type
to scan for type
- but the script breaks with browser finished
. Is there something obvious that I’ve missed? Many thanks again.
I finally read your sample code above and tried this, but it won’t let me run it twice because it says the browser already exists. Is there a way to remove it, not just stop it?
tell application "Bonjour Events 2.1"
-- create new browser instance, the name property is mandatory
set AFPBrowser to make new browser with properties {name:"MyBrowser"}
tell AFPBrowser
scan for type "_ipp._tcp." in domain "local" time out after 10.0 -- default time out value is 5.0
end tell
(*
alternatively set the properties in separate lines
tell AFPBrowser
set domain to "local" -- default is "" (any domain)
set service type to "_afpovertcp._tcp"
scan
end tell
*)
set {scan error:scanError, timed out:timedOut, bonjour services:bonjourServices} to result
if scanError is not missing value then
-- do some error handling
else if timedOut then
-- handle time out
else if (count bonjourServices) > 0 then
set firstService to item 1 of bonjourServices
tell firstService
set ipv4Address to IPv4 address
set theHost to host
end tell
end if
-- Bonjour Events quits automatically after 5 minutes of inactivity
-- this doesn't seem to work
-- tell browser "MyBrowser" to stop
end tell
Version 2 allows to create multiple browsers. And waiting for completion is not necessary, the browser waits itself
try
tell application "Bonjour Events"
if (exists browser "MyBrowser") then
set IPPBrowser to browser "MyBrowser"
else
set IPPBrowser to make new browser with properties {name:"MyBrowser"}
end if
tell IPPBrowser
scan for type "_ipp._tcp" in domain "local"
if (count services) > 0 then
set nameList to name of services
set addressList to IPv4 address of services
else
set nameList to {}
set addressList to {}
end if
quit
-- Bonjour Events quits automatically after 2 minutes of inactivity
end tell
end tell
on error errorMessage number errorNumber
display dialog "An error occurred: " & errorMessage & " (" & errorNumber & ")"
end try
Alternatively delete the browser right before calling quit
try
tell application "Bonjour Events"
set IPPBrowser to make new browser with properties {name:"MyBrowser"}
tell IPPBrowser
scan for type "_ipp._tcp" in domain "local"
if (count services) > 0 then
set nameList to name of services
set addressList to IPv4 address of services
else
set nameList to {}
set addressList to {}
end if
-- Bonjour Events quits automatically after 2 minutes of inactivity
end tell
delete IPPBrowser
quit
end tell
on error errorMessage number errorNumber
display dialog "An error occurred: " & errorMessage & " (" & errorNumber & ")"
end try
@StefanK - I know there are many reasons to say No to this, but I hope it is OK to ask:
Would you consider making Bonjour Events open-source, so that it could be used in packages that require open-source software? I can find no other software that can do what Bonjour Events does, so this would be very useful. But of course I understand and will not complain if you don’t want to do this.
Thank you again for this superb utility.
BTW
Has anyone had any luck using NWBrowser in “Network” Framework to use Bonjour in AppleScriptObjC?