Shane wrote the script below years ago, and it’s terrifically useful (thank you, Shane…). I’ve spent the past few hours trying to figure out how to limit the list of printers to those that are online and available, and I can’t make any progress. Can anyone provide a pointer to the answer? Many thanks, as always.
EDIT: I found this thread, but can’t figure out how to adapt the Swift-related information linked at the end to AppleScript. I think what I want is PMPrinterState but that’s as far as I can get.
-- Created 2015-08-11 by Shane Stanley
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"
set theNames to current application's NSPrinter's printerNames() as list
set printerName to (choose from list theNames with prompt "Choose a printer:")
if printerName = false then error number -128
set thePrinter to current application's NSPrinter's printerWithName:(item 1 of printerName)
set thePrintInfo to current application's NSPrintInfo's sharedPrintInfo()
thePrintInfo's setPrinter:thePrinter
And, if I’m reading the documentation correctly (something that is NOT guaranteed), it seems that PMPrinterGetState doesn’t report whether a printer is onine or offline, so I’ll keep looking.
@peter - Unfortunately, current macOS lpstat doesn’t provide this information. The idea of adapting Naganoya-san’s code is interesting. I will see if I can figure out how to do it. Thank you.
Hm, but it certainly helps to see which printers answer to which service type query.
So if this doesn’t help, Naganoya-san’s code won’t help you either, I am afraid.
@peter - Now that I’m back at my home setup, it turns out that you’ve pointed me toward the answer. The command
dns-sd -B _printer._tcp
lists available network printers, and presumably variations on that command can list other printers. One difficulty is that the DNS name of a printer does not need to be the same as the macOS lpstat -p printer name or the queue name, but this can presumably be sorted out. Meanwhile, belated but heartfelt thanks.
It turns out that the answer to this was in an ancient thread where StefanK did all the work:
And a script that displays only networked IP printers is here. It’s horribly slow, but it seems to work (and I could probably get rid of quite a bit of it):
-- Display a list of available networked IP printers
-- by Edward Mendelson, using code adapted from many posts at MacScripter.net
-- requires "Bonjour Events" by Stefan Klieme, downloadable here:
-- http://www.klieme.ch/pub/Bonjour%20Events.zip
set noPrinters to 0
try
set printerNames to (do shell script "lpstat -l -p | grep -i Description: |awk -F'Description: ' '{print $2}' ") -- as list
on error
set noPrinters to 1
end try
if printerNames = "" then
set noPrinters to 1
end if
if noPrinters is 0 then
try
set queueNames to (do shell script "lpstat -a | awk -F' accepting' '{print $1}'") -- as list
on error
set noPrinters to 1
end try
end if
if noPrinters = 0 then
try
set printerList to (every paragraph of printerNames) as list
set queueList to (every paragraph of queueNames) as list
end try
set item_num to 0
set ipPrinterList to {}
repeat with j in printerList
set thePrinter to j
set item_num to item_num + 1
set theQueue to (item item_num in queueList)
set dnsURL to do shell script "lpstat -v " & theQueue
set dnsString to (do shell script "perl -e 'use URI::Escape; print uri_unescape(\"" & dnsURL & "\")';")
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
set ipPrinterFound to false
repeat with currentItem in nameList
if currentItem is in dnsString then
set ipPrinterFound to true
set currentListItem to currentItem as item
set dnsNumber to my list_position(currentListItem, nameList)
set printerIP to item dnsNumber in addressList
copy thePrinter to the end of ipPrinterList
-- tell me to activate
-- display dialog thePrinter & return & return & "has the DNS instance name" & return & return & currentItem & return & return & "IP address:" & space & printerIP & return & return & "queue name:" & space & theQueue buttons {"OK"}
exit repeat
end if
end repeat
end repeat
tell me to activate
set chosenPrinter to choose from list ipPrinterList
set chosenPrinter to item 1 of chosenPrinter
set printer_num to my list_position(chosenPrinter, printerList)
set theQueue to (item printer_num in queueList)
display dialog "You chose:" & return & return & (chosenPrinter as string) & return & return & "queue name:" & return & return & (theQueue as string) buttons {"OK"}
error number -128
else
tell me to activate
display dialog "No printers found!" buttons {"OK"}
error number -128
end if
on list_position(this_item, this_list)
repeat with i from 1 to the count of this_list
if item i of this_list is this_item then return i
end repeat
return 0
end list_position
StefanK’s Bonjour Events app no longer seems to be available, and I see that there was once a version 2.1 of the app. It would be good to have it again.