3

I am writing a console application in .Net Framework 4.8 that will run as a Windows service. It should be possible in this console application to send a file to a printer (installed on the same pc as where the Windows service is running). However I find this quite challenging and haven't found a suitable solution. I have no control about what else is installed on the pc (for instance Adobe Acrobat Reader). The following things I already tried are:

  • Using the PrintDocument class from .net (this seems to be for creating the content of what needs to be printed at runtime not for already existing files)
  • Using System.Printing (this can't be used for windows services as stated in their documentation here)
  • using a process with verb 'print' and 'printto' as described in this Stack overflow post
  • I ended up using this Nuget package. Which works for .txt and .pdf but not for .docx files for instance. I would like to be able to print different sorts of files.

What am I doing wrong? I would think this is straight forward but apparently not. Which makes me think I am looking at it from the wrong angle so to speak. Are there any examples available or Nuget packages to help me achieve this? If you need any other information, please ask me.

Tijl .Reynhout
  • 901
  • 2
  • 9
  • 24
  • 1
    How would you print a .DOCX file without something to interpret and render the file. You can't run Word from a service (https://theether.net/download/Microsoft/kb/288367.html), so you'd need to find some printing package that is capable of rendering the file. If you "send a file to the printer" from the desktop, you are activating the default application for that file type and sendin the "Print" verb. If you do that with a DOCX file, you'll see Word start up. But, running as a service comes with a lot of caveats (see that knowledge base article). – Flydog57 Jun 04 '21 at 14:43
  • So is the safest bet then trying to convert all file types to pdf's and then printing those pdf's? – Tijl .Reynhout Jun 04 '21 at 14:59
  • Actually, if you can convert things to XPS format (https://en.wikipedia.org/wiki/Open_XML_Paper_Specification), you'd likely be slightly better off. I believe Windows printer drivers are XPS-based – Flydog57 Jun 04 '21 at 15:12

2 Answers2

0

It sounds like you need a library that supports rasterizing and rendering the various file formats that you are interested in via a windows service or console application. You can check out the Leadtools.Document.sdk nuget package (please note I am an employee of this vendor).

I went ahead and put together a project to test this out and it worked for me. I am able to print any of the 150+ file formats that the sdk supports. For a full list of supported file formats see here.

Here is the sample code:

using (var document = DocumentFactory.LoadFromFile(@"filename.docx", new LoadDocumentOptions()))
    PrintDocument(document);

static void PrintDocument(LEADDocument document)
{
   using (var printDocument = new PrintDocument())
   {
      printDocument.PrinterSettings.MinimumPage = 1;
      printDocument.PrinterSettings.MaximumPage = document.Pages.Count;
      printDocument.PrinterSettings.FromPage = 1;
      printDocument.PrinterSettings.ToPage = document.Pages.Count;
      printDocument.PrinterSettings.PrinterName = "Adobe PDF";
      printDocument.DefaultPageSettings = new PageSettings();

      var pageNumber = printDocument.PrinterSettings.FromPage;

      printDocument.PrintPage += (object sender, PrintPageEventArgs e) => PrintPageHandler(e, document, printDocument, ref pageNumber);
      printDocument.Print();
   }
}

private static void PrintPageHandler(PrintPageEventArgs e, LEADDocument document, PrintDocument printDocument, ref int pageNumber)
{
   PrintPage(document, pageNumber, e);
   pageNumber++;

   e.HasMorePages = (pageNumber <= printDocument.PrinterSettings.ToPage);
   if (!e.HasMorePages)
      pageNumber = 1;
}

static void PrintPage(LEADDocument document, int pageNumber, PrintPageEventArgs e)
{
   var page = document.Pages[pageNumber - 1];

   // Get page size in pixels
   var pixelSize = page.SizeToPixels(page.Size);
   // Convert to DPI
   var size = LeadSizeD.Create(pixelSize.Width * 96.0 / page.Resolution, pixelSize.Height * 96.0 / page.Resolution).ToLeadSize();
   // Fit in the margin bounds
   var destRect = LeadRect.Create(e.MarginBounds.X, e.MarginBounds.Y, e.MarginBounds.Width, e.MarginBounds.Height);
   destRect = RasterImage.CalculatePaintModeRectangle(size.Width, size.Height, destRect, RasterPaintSizeMode.Fit, RasterPaintAlignMode.Center, RasterPaintAlignMode.Center);

   // Get the page image
   using (var rasterImage = page.GetImage())
   using (var bitmap = RasterImageConverter.ConvertToImage(rasterImage, ConvertToImageOptions.None))
      e.Graphics.DrawImage(bitmap, destRect.X, destRect.Y, destRect.Width, destRect.Height);
}
hcham1
  • 1,799
  • 2
  • 16
  • 27
0

After comparing different libraries for printing (and pdf manipulation) we went for Gembox.Pdf to meet the requirements. This allows us to print pdf, png, jpg and more from a windows service.

Tijl .Reynhout
  • 901
  • 2
  • 9
  • 24
  • Are you happy now with Gembox.PDF ? – Kemal AL GAZZAH Nov 27 '21 at 10:29
  • Yes, it fits our needs. The only thing we were not able to do is convert a pdf to an image in an azure function so we needed to use a work around. If this would become available in the future, I would like to get an update :) – Tijl .Reynhout Nov 29 '21 at 08:59