Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to print documents from a .net core 3.1 Windows Service?

tl;dr How can you print pdfs from a .net Core 3.1 Windows Service?

I've created a simple print spooler BackgroundService class, which is being run as a Windows Service, and monitors a print queue via a web api, all very happily.

The small problem I've discovered as started to write the actual printing code is that it seems .net core doesn't want people to print documents from BackgroundService classes.

The docs for System.Printing seem to suggest this anyway.

Classes within the System.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.

System.Drawing.Printing has a similar note in its docs, stating that it will not work reliably for Windows Services either.

Is printing from a BackgroundService Windows Service a bad thing (tm)? Is there an obvious alternative to System.Printing / System.Drawing.Printing, that my (brief) googling has failed to find? The printing requirements should be pretty simple, I've got pdf byte array data, that I just need to get to a printer somehow).

I realise I could do something like convert the spooler to a Console app, and run it from a Scheduled Task, but the Windows Service model seemed like it'd be simpler to just install and forget (it's destined for a PC next to a printer in a warehouse)

Any helpful suggestions would be much appreciated

like image 445
Ted Avatar asked Sep 17 '20 16:09

Ted


1 Answers

Incredibly, we did manage to achieve the impossible - printing PDFs from a .net Core 3.1 Windows Service.

We use the FreeSpire.PDF v5.4.0 nuget package and the following code to print pre-generated pdf data, to a Zebra Label printer.

bool printedOK = true;
string printErrorMessage = "";
try
{
    PdfDocument pdf = new PdfDocument(printJobResult.printJob.PrintData);
    pdf.PrintSettings.PrinterName = jobInfo.PrinterAddress;
    pdf.PrintSettings.DocumentName = jobInfo.Type == PrintJobType.Label ? $"Label {jobInfo.OrderNumber}" : $"DeliveryNote {jobInfo.OrderNumber}";                                    
    if(jobInfo.Type == PrintJobType.Label)
    {
        pdf.PrintSettings.PaperSize = new System.Drawing.Printing.PaperSize("Custom", _labelWidth, _labelHeight);
        pdf.PrintSettings.SetPaperMargins(2, 2, 2, 2);
    }
    pdf.PrintSettings.SelectSinglePageLayout(Spire.Pdf.Print.PdfSinglePageScalingMode.FitSize, true);
    _logger.LogDebug($"Paper Size - Width:{pdf.PrintSettings.PaperSize.Width} Height:{pdf.PrintSettings.PaperSize.Height} Name:{pdf.PrintSettings.PaperSize.PaperName} Kind:{pdf.PrintSettings.PaperSize.Kind} RawKind:{pdf.PrintSettings.PaperSize.RawKind}");

    pdf.Print();
}
catch (Exception ex)
{
    printErrorMessage = "Printing Error: " + ex.ToString();
    printedOK = false;
}

Note to self - Do go and check the details of these following points...

Newer versions of the FreeSpire.PDF plugin don't allow printing, and I believe there are limits even with the 5.4.0 version (10 pages of printing I think), but for our purposes, the 5.4.0 version of the plugin has allowed us to create a tidy little delivery label print spooler, running as a Windows Service on a warehouse PC.

like image 95
Ted Avatar answered Oct 26 '22 12:10

Ted