Printing (to a physical printer) on Windows

First, let me say that my question is very open-ended, because there are a ton of different possible ways to solve the problem.

I'm writing a program that watches a folder for new JPEG images and prints them, sharing the print queue across a pool of printers (connected via USB). I run a family photo printing operation at a soup kitchen every holiday season, so we set up a few, good desktop printers, a laptop, local WiFi network for transferring photos, etc. This program is the linchpin of the whole operation. I wrote a quick-and-dirty prototype in C#/WPF back in 2017 that worked like a charm for 3 years, but it failed with this year's dry run, so I took it upon myself to write a production-ready application in Rust. Everything except printing works: I use the notify crate to watch the folder, crossbeam for inter-thread communication and a shared printer queue, and so on.

There are two parts of the program I haven't figured out yet, and I'm hoping someone else might be able to help.

The first and most important part is printing! I need some way to save a user's settings for a specific printer and print images using those settings each time (e.g. 4"x6" paper, a particular paper type, borderless).

I tried using the windows crate to print using a Windows API. I mostly write software on Linux, so I'm not terribly knowledge about Windows libraries. It seemed like creating and XPS document and using an XPS printer was maybe the most modern and universal way to print, so I tried that. I'm not even sure it's worth mentioning everything that stopped me in my tracks; this seems like it would take me days or weeks to sort out, and the event is about 24 hours away.

I'm tempted to try the wxWidgets printing API, at least for now. (The application is currently terminal-based because of time constraints, so I don't mind using whatever dialog or framework solves the problem.)

It seems like using lpr or mspaint with command-line options might work, if I can simply set default settings on the printers and they then use those settings for all print jobs.

Edit: I also need to be able to check (e.g. poll) printer status so I only retrieve jobs from the shared print queue when a printer is actually idle. We do sometimes have to print manually, replace ink cartridges, etc. Sending a print job to an external program like mspaint doesn't solve this problem, unfortunately. Also, I don't think lpr is available on Windows 10 Pro.

Does anyone have ideas, solutions, advice about which paths to try, etc.? I'd love guidance from someone more experienced in any of the above subject areas.

The second, and far less important, area of concern is reading JPEG images so I can draw them. I haven't looked into this much, but any recommendations I'm assuming I'll use the image library, unless advised otherwise.

Thanks very much!

The following thread had a pretty similar discussion, and it seems to me that the solution provided worked:

Yes, for reading the image into a matrix of pixels, this is the library to use.

1 Like

Thanks! Perhaps I should have mentioned this, but that post was actually my jumping-off point. It very broadly answers the question, i.e. "use Windows' print facilities, and here's how to do that from Rust," but that's about as far as it goes.

I banged my head against this a little while ago and got some stuff working using the XPS apis. It's not trivial, but it's not as bad as I feared!

From memory, the main thing is there's a whole lot to try to wrap up if you want to keep it safe, but it's not super difficult to use the winrt stuff (the stuff not in Win32) directly anyway. I suppose the thing would be to provide a Piet backend or the like...

Thanks for the words of encouragement and the directions to explore! I really appreciate the tips. This year's event went superbly (other than a printer that died 15 minutes in). Now I can poke at the WinRT XPS printing API and Piet in a less hurried way.

While you could, and it might even be useful if you want to live edit, a Piet backend would be more a project for making something for public consumption. For some internal use I found it pretty straightforward to directly use the XPS DOM from the API.