1
votes

Is there a way to programatically lock a network print device before printing a large batch of documents and release it after? We predominantly use C#, VS2010, .NET 4.0 Framework.

Our company has a lot of established processes that involve a great deal of printing. Many of these involve programatically printing a particular small document repeatedly, with different parameters each time. The result is a large batch of a few hundred pages that need to be in order.

Unfortunately, since the batch is sent to the printer as a series of small jobs rather than a single large job, should another user print to the same printer in the meantime, their job is liable end up between pages of the large batch, thereby messing up the order of the large batch, causing a search for a needle in a haystack, and frustrating the heck out of the user who printed the large batch.

Apparently this birthed a culture in our company, in which every time a user is about to print, they send out a mass e-mail to the entire company saying "I'm printing to such and such printer, I'll be using it for about an hour, please don't print to it, I will e-mail again when I am done."

I'd like to be able to programatically lock a printer, submit the batch of ordered print jobs, and then release the printer. Ideally, jobs could still be submitted to the printer but they would have to wait in queue until after the large batch finishes and the printer is released. Unfortunately, we haven't had much success pursuing that goal in the past. Has anyone else solved a similar situation using .NET?

3
It would probably depend on the printer driver. If the driver you have doesn't support this feature then you could maybe write a wrapper to it, that basically just adds the locking feature. Then have your program trigger the lock in your custom driver wrapper. Or maybe look into some sort of print server system...FrustratedWithFormsDesigner

3 Answers

1
votes

FrustratedWithFormsDesigner's idea of wrapping the Windows print driver could work if all the clients of the printer are Windows machines. If you had Macs, Linux boxes, or other devices connecting to the printer as well, you would need to implement a similar wrapper for each of those systems.

It sounds like you need an application that can batch each of these jobs into a single print job.

Several companies produce a free PDF print driver. I've used the Bullzip PDF driver before with good success.

You could then use a C# library like iTextSharp to combine the resulting PDFs into a single large document, which would get printed as a single job.

1
votes

Solution 1: If you write or have access to the code submitting the jobs This will effectively create 1 big job, and will keep them together, even if jobs are submitted from other workstations and servers.

In this case you can submit multiple jobs, and call the SetJob function with a JOB_INFO_3 structre within the Spooler API to link one job to the next.

All jobs must be linked before their spooling is completed with the call to EndJob.

This is more completely documented in the Remarks section for SetJob.

Solution 2: Alter Priority This will keep the jobs together provided this server\workstation is the only source submitting to the printer.

Assuming you are submitting jobs in order, you can set the Priority using the SetJob function with a JOB_INFO_1 structure, and up the priority. You will want to call GetJob first to populate the JOB_INFO_1 structure, change the priority, and then call SetJob.

0
votes

Printers, or rather printer queues, have ACLs in Windows. Changing the ACL so only a single user has Print permission should be possible.

It will mean giving everyone Change Permissions permission on the printer (and ensuring you remove that permission white printing from everyone else white processing a batch).

I would also suggest some sort of reset (maybe on schedule) in case the batch printer fails in some way so permissions are not restored.

This will require P/Invoke.

  1. Call GetPrinter with level 3 and a PRINTER_INFO_2 instance will get you the current security descriptor.
  2. Update the SECURITY_DESCRIPTOR referenced by PRINTER_INFO_2.pSecurityDescriptor with the replacement ACL (and keep the original).
  3. Call SetPrinter with the updated PRINTER_INFO_2.

Repeat the process, using the saved ACL to restore. I assume this will need to be performed on the server that host's the queue.

(Using some method to send everything as a single document may well be easier, and avoid having everyone being able to change the queue's permissions.)