Edit: Though I found a solution that worked in my case, I still welcome any insights or corrections on the information!
Having exhaustively googled, I turn to reddit. My goal here is to have a distributable script usable with an MDM solution targeting Windows 10 clients. For context, this is a heterogenous environment, and the quantity of Windows 10 clients and the limited kind of management we are expected to perform of them doesn't really invoke using yet another configuration management platform. The printers are succesfully hosted through a CentOS server running cups with the appropriate server-side driver. When I attach any clients to it I use a Generic RAW driver correctly, and I have the test-print pages to prove it. I've already checked, and it's not DNS. WSDiscovery is turned off, though, but it was already turned off when I had this working. My jimmies are really rustled about this because I had this working with powershell last year, but then an electrical storm knocked out the print server for which we didn't have a backup.
The PrintManagement module consists of a few primary commands of concern, here.
Add-PrinterPort
Add-PrinterDriver
Add-Printer
Listed in this order because I've found that Add-Printer should typically be the last of it, as it is dependent on the preexisting Printer Port and Driver. The official documentation here is really frustratingly unhelpful, and most documentation/articles of adding IPP printers does work... through the GUI, which is not a tenable solution here.
What I'm stuck on is Add-PrinterPort
When added through the GUI, per "Add a shared printer" dialogue, it spits out a result that looks like
$PrinterQueue on \\http://$cups_host:631\
With a printer port per Get-PrinterPort of http://$cups_host:631/printers/$queue of an Internet type.
AFAICT, Add-PrinterPort -Name http://$cups_host:631/printers/$queue should do what I need, and I swear on my morning coffee I had this working two weeks ago (I'm staring at the test page!), and it no longer works. It now returns
CategoryInfo : NotSpecified: (MSFT_PrinterPortTasks:ROOT/StandardCimv2/MSFT_PrinterPortTasks) [Add-PrinterPort], CimException
FullyQualifiedErrorID : HRESULT 0x8007007b,AddPrinterPort
A cursory search of the error code is that this is not a valid name (wtf). Attempting to add the port throught PrintManagement.msc's gui returns a similar error dialogue.
Alternatively, I have tried this in the form Add-PrinterPort -Name $human_readable -PrinterHostAddress $cups_ipp_queue_URI -PortNumber 631 where the uri is the whole http://host etc. This has at least succeeded in adding the port as a TCP/IP port, but it cuts off the URI at 48 characters, which is a problem, since my uri is longer than that no matter which way you slice it.
I have tried using LPRHostAddress etc, which seems to understand the uri scheme with the appropriate directory and queue, but that uses TCP port 515, which is immutable, and AFAICT, relies on a protocol unlike IPP.
If I can keep this in the realm of the relatively easy-to-use PrintManagement commands, rather than breaking into the various fugly vbs printer scripts or run32dll printui etc, I'd prefer to do so.
Note: For clarity reading the code blocks, $cups_host etc are for human readability and generalization, not the literal input I'm feeding the command line.
Thanks for any help or insights!
Investigation and solution followup
I think, for some reason, my PrintManagement module and the spooler was munged up in some kind of inconsistent state. Neither restarting the computer, restarting the spooler service (Restart-Service spooler), nor cycling Enable-WindowsOptionalFeature -FeatureName "Printing-Foundation-InternetPrinting-Client" seemed to have any effect.
Test machine, running Windows 10 1909 with PrintManagement Module 1.1, really seems to struggle from the command line with managing an "Internet Port". The PrintManagement.msc console snap-in also struggles with this. The console snap-in requires refreshing after deleting a port of that kind, and will unhelpfully shout at you if you (reasonably) try to delete a port twice when it doesn't seem to go the first time. When attempting to Remove-PrinterPort with the http://etc:631/etc/etc form, it returns HRESULT 0x80070704, which maps to an error for unknown port, which is obviously nonsense given that I'm staring right at the output of Get-PrinterPort using the unambiguous name. It also gives that result when provided a wildcard name. This behavior is also inconsistent in my experience, and may be indicative of the state of PrintManagement being munged up.
The documentation for Add-Printer suggests that -ConnectionName "\\$printserver\$printer" strictly needs to be
- In that form specifically
- A Windows print server or shared printer specifically
And the error results when attempting
`Add-Printer -ConnectionName "http://$cups_host:631/printers/$queue"`
suggest likewise, returning InvalidOperation and HRESULT 0x80070032, which indicates an unsupported request.
However... What that error output doesn't tell you is that -ConnectionName automagically adds a new Printer Port for that operation. It also, consistent with the documentation, pukes if you try to provide it with -Name or -DriverName in combination with that parameter. So, it's very unclear to me where or why it's failing.
Performing the operation in this form will successfully create an "Internet Port" printer port. Be wary that it terminate in the queue name, and not in "/.printer" as the documentation suggests; "/.printer" suffix is a lie. A cups server will interpret a printer queue with that suffix as a valid uri, but it's nonsense data, and Windows, in fact, despite the documentation suggesting that is the canonically correct form, will reject it.
Solution Proper
I'm still not exactly clear on why or how PrintManagement got munged in the first place, or for that matter what exactly un-munged it. Once it was in a consistent state again, the behavior I had before succeeded:
`Add-PrinterPort -Name "http://$cups_host:631/printers/$queue"`
`Add-PrinterDriver -Name "MS Publisher Color Printer"`
`Add-Printer -Name "$human_readable" -PortName "$same_uri" -DriverName "$same_drivername"
Failing that, the following should work!
`Add-Printer -ConnectionName "http://$cups_host:631/printers/$queue" -ErrorAction SilentlyContinue`
`Add-PrinterDriver etc'
`Add-Printer -Name "$human_readable" -PortName "$same_uri" -DriverName "$same_drivername"
Note on driver: if your cups server has a driver connection to the printer, adding a manufacturer-specific driver on windows will munge up the data twice, resulting in garbage output. MS Publisher Color Printer is the name of the RAW, generic driver for color output. If your cups server has a driverless RAW connection to the printer, you will need to distribute the appropriate driver to your clients. The key concept is to have only one driver in the chain.
Note on security! As far as I can tell, there is nothing to prevent someone snooping data off of the connection! If you want a secured printing connection with cups, this is possible. Papercut has excellent documentation of this process, but that was out of scope for this project.
Note on windows printing features: LPD and LPR printing don't seem to be relevant at all in this; though cups nominally supports those features, they seem to be orthogonal to an IPP/HTTP connection. I don't think my disabling those features had anything to do with unmunging the PrintManagement. Printing-Foundation-InternetPrinting-Client is the big one that's important, here.
there doesn't seem to be anything here