UPDATE: Be sure to check out my follow post: Configuring Printers Programmatically for AirPrint Part 2: Now with Icons!
For the past several weeks, I’ve been troubleshooting an issue one of our users reported when printing large MB files to an HP Color LaserJet Pro M452.
Historically, we’d had trouble getting these M452s to print jobs sent from Macs routed via our print server and temporarily configured direct IP printing to work around it. However, after upgrading to macOS Mojave (10.14.6) this year and temporarily implementing a solution proposed on Jamfnation to get things working with our print server, we ran into a different set of issues entirely.
While test pages and files ~5MB in size would print just fine, files closer to ~10MB would take an exceptionally long time to process – getting stuck spooling at several points – and when ultimately finished after several minutes only printed out the following error:
ERROR: limit check OFFENDING COMMAND: showpage
Interestingly, the print experience was the same regardless if we were going through our print server, via direct IP, and even via a physical USB connection.
Given our previous issues with print server printing, I tried the following for direct IP printing (lpd://
), all with no success:
- Using both the available driver from HP’s website and Generic Postscript Printer driver
- Testing different file types totaling ~10MB, including saving several large test images as PDFs before printing
- Manually adding the printer via the ‘Add Printer’ menu as well as programmatically
- Booting the test Macs to Safe Mode
- Testing with different Macs running 10.14.6
- Attempting to upgrade the firmware of the printer itself using the HP firmware update utility failed to transfer
- Upgrading the Macs running 10.14.6 to the latest available supplemental update
The one thing that did successfully print ~10MB files without issue were Macs running 10.13.6. So, something is definitely not happy in Mojave …
We went so far as to purchase a new HP M454, but unfortunately ran into the same issues.
Desperately hoping for a long-term solution, I reached out to Apple Enterprise support, and after being escalated was able to confirm with the advisor that the printer error we were seeing is a known issue. Besides confirming that most issues reported were with HP printers, it has also been identified both on 10.14 and 10.15 …
The only good news here was that there is a known workaround available: configure printing via AirPrint. Having handled all our printing configurations with the help of PrinterGenerator, I needed to figure out how we could programmatically setup AirPrint our few M452s and new M454s.
With some help with members of the #printers-n-cups MacAdmin Slack channel, I learned that AirPrint utilizes the ipp
protocol. When manually configuring a printer for AirPrint, a built-in macOS tool is used called ipp2ppd
(/System/Library/Printers/Libraries/ipp2ppd) and which creates a ppd file in /etc/cups/ppd
.
Running ipp2ppd
with no arguments reveals it’s usage:
Usage: ipp2ppd <printer_uri> <input_ppd_path>
With the printer installed for AirPrint manually, you can get the settings with lpoptions
, critically the device-uri
, which we need for <printer_uri>:
# To get printer names lpstat -e # Get printer settings lpoptions -p <printer_name>
In our case, we’re working with ipp://
rather than dnssd://
. With the printer uri, the last piece is supplying a ppd path. A little searching on Jamfnation revealed the buried built-in AirPrint.ppd file (although you can just supply everywhere
and get the same result):
/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Versions/A/Resources/AirPrint.ppd
Now, running the ipp2ppd
tool with the required arguments produced the necessary ppd information! Albeit, to stdout. Redirecting to a file produces the needed ppd file.
/System/Library/Printers/Libraries/ipp2ppd ipp://<printer_ip> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Versions/A/Resources/AirPrint.ppd > /path/to/<printer_name>.ppd
Because this file normally gets created in /etc/cups/ppd
, you can simply redirect the output to a file there. In my tests, this must be done as root
.
With the AirPrint ppd file created, you’ll want to test using it to install the printer:
lpadmin -p <printer_name> -D "<printer_display_name" -L "<printer_location>" -E -v ipp://<printer_ip> -P /path/to/<printer_name>.ppd
With the printer installed programmatically, we can test printing our large image file and verify that a ~10MB file now successfully prints!
If you happen to use PrinterGenerator or a similar munki nopkg
item to install your printers via postinstall_script, I created the preinstall_script below to create the necessary AirPrint ppd file via ipp2ppd
:
A Small Caveat …
The one caveat I found is that running this script as a local user produced a slightly different ppd file than when run as root
.
Mysteriously, the ppd has a single line that is different when run as root
: it did not have a printer icon listed. Run as a local user, the printer’s icon file is copied to /Library/Printers/Icons
and is then referenced in the ppd file.
This missing icon behavior occurred both when adding sudo
as well as when attempting to run by root
(running sudo -s
) as a local user (ex. as root: sudo -u <username> ipp2ppd ...
). With the help of a fellow Mac Admin in the MacAdmins #printers-n-cups channel, we found that a local user could successfully get the icon when run as root
by adding the -E
flag:
sudo -E -u <user> ipp2ppd ipp://<printer_ip> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Versions/A/Resources/AirPrint.ppd > /path/to/<printer_name>.ppd
Unfortunately, this doesn’t really help us because when run via munki, Jamf, or some other method it will still run as root
. So as of yet, I’ve been unable to programmatically configure AirPrint printers which also include the printer icon.
With a little help from Wireshark, I was able to determine that as part of its printer attributes query (you can run this manually by running ipptool -tv ipp://<printer_ip>/ipp/print get-printer-attributes.test
) ipp2ppd
uses the printer-icons
information collected to download 3 files (in the case of the M452):
'http://<printer_ip>/images/printer-small.png' 'http://<printer_ip>/images/printer.png' 'http://<printer_ip>/images/printer-large.png'
Once downloaded, these are converted & merged into a single .icns
file which is populated in /Library/Printers/Icons
. The traffic shows that these .png
files are also collected when ipp2ppd
is run as root
, but does not produce this .icns
file and likely why it does not then subsequently include this in the final ppd file.
Despite not being terribly important on the whole, this does itch my curiosity and my hope for an eventual fix.
Thanks for your work! We have picked up at your Wireshark findings and do a query with ipptool, gather the urls of the printer-icons, download them, and generate the needed iconset/icns file on the fly.
May be helpful for others as well:https://github.com/wycomco/airprint-ppd
LikeLike
This is great! Ty!
LikeLike
OMG, I have just found your more recent blog post with your solution for the icons… This would have definitely saved me some time. 😅
LikeLike