question

ManivannanD-5068 avatar image
0 Votes"
ManivannanD-5068 asked XiaopoYang-MSFT commented

C# Printing problem with system.Drawing.Printing from #web API

 Hello everyone,
    
 I have a situation to print PDF document as a batch from Web API. 
 And I have used System.Drawing.Printing Library to print them.
    
 I have noticed the ‘Caution’ mentioned on Microsoft site (https://docs.microsoft.com/en-us/dotnet/api/system.drawing.printing?view=net-5.0) as below.
    
 Specifications:
 1)    We are using network printers.
 2)    Windows server 2016 standard.
    
 Caution:
 Classes within the System.Drawing.Printing namespace are not supported for use within a Windows service or ASP.NET application or service. 
 Attempting to use these classes from within one of these application types may produce unexpected problems, such as diminished service performance and run-time exceptions.
    
 As mentioned in the caution I am facing some unexpected problems intermittently during print operation as below.
    
 Problems:
 1)    Pages are missing in the PDF documents. Example: Out of 10 pages 5th page is missed.
 2)    Documents are missing, example: out of 100 documents 99/ 95 printed. Some of them is missed. 
    
 Exception occured in PrintPdf method: The handle is invalid System.ComponentModel.Win32Exception (0x80004005): The handle is invalid
    at System.Drawing.Printing.StandardPrintController.OnStartPrint(PrintDocument document, PrintEventArgs e)
    at System.Drawing.Printing.PrintController.Print(PrintDocument document)
    at System.Drawing.Printing.PrintDocument.Print()
    
    
 Code snippet:
    
     using (var document = _pdfDocumentWrapper.Load(stream))
                 {
                     using (var printDocument = _pdfDocumentWrapper.CreatePrinterDocument(document))
                     {
                         var printerName = printerconfiguration;
                         Print(printDocument, printerName);
                     }
                 }
        
     private void Print(PrintDocument printDocument, string printerName)
             {
                                    
                 var printerSettings = new PrinterSettings { PrinterName = printerName };
                 var pageSettings = new PageSettings(printerSettings) { Margins = new Margins(0, 0, 0, 0) };
                 printDocument.PrinterSettings = printerSettings;
                 printDocument.DefaultPageSettings = pageSettings;
                 printDocument.PrintController = new StandardPrintController();
                 printDocument.BeginPrint += PrintDocument_BeginPrint;
                 printDocument.PrintPage += PrintDocument_PrintPage;
                 printDocument.EndPrint += PrintDocument_EndPrint;
                    
                 printDocument.Print();
             }
    
 Any suggestions or alternative approach for the same would be greatly appreciated.


windows-apiwindows-wpf
· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Maybe you are running the c# program in 32 bit mode on a 64 bit server which causes the application to run in isolation mode. According to this thread, isolation mode cause the problem.
The print function try to connect to a 32 bit driver rather than the 64 bit drivers that were installed can also caused the problem or the printer driver is out of date .



0 Votes 0 ·

1 Answer

cooldadtx avatar image
0 Votes"
cooldadtx answered

It really depends upon what you intend to do with that printout. If you're printing a physical document for a user then how do they get the document. Your web server could be hosted on premise or the cloud. It might or might not have access to a printer near the person who needs it. In most cases the better solution is to do the printing client side. You can write javascript to print a batch of PDFs on the printer(s) available to the client. This eliminates the need for server-side printing. Of course the user could also just open the PDF and print from their PDF viewer as well.

If you need to print the PDF so you can manipulate them then don't bother printing, just use a PDF library like iText or equivalent and do your PDF manipulation.

If you really need to print a PDF to a printer then, ignoring the issue of the printer not being accessible, you'll want to move the process out of band. In the few cases where I've needed to do this we created a simple console app that did the printing. The console app was run using the Process task but it ran using credentials of a local user which ensured the local printers on the machine were used. Of course this has bad performance since starting a process with an interactive user is going to be slow (relatively speaking). You could also create a console app that hosts a WCF service (or if you're using .NET Core then hosting Kestrel directly) that your API then communicates with. The console app would need to be started when the server starts but shouldn't really be a Windows service since that is not supported either. There are loads of problems with this approach but it helps perf a little bit.

Finally the best option, in my opinion, is to write a batching processor that runs periodically (via scheduled tasks perhaps). The API would simply add the print request to some shared queue (probably a database or messaging queue). The batching processor, when it runs, would pick up things to print and then print them. If using a database then the processor could update the status when done. The API would provide a corresponding endpoint to check the status of the printing so the user could be notified (if relevant). Note that the API would not want to wait on the printing to complete as it could take longer than a web request. This is what the 202 HTTP status code is for - I've started the processing but I'm not done yet, here's some ID that you can use to query for the completion status later.

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.