ARTICLE

Printing From a Windows Service

Posted by Varun Bansal Articles | Windows Services in C# November 07, 2012
I got a requirement for printing using a Windows Service. So I searched the internet and found some examples and finally two of them worked for me, So I am posting the working ones here.
Reader Level:
Download Files:
 

Requirement

Recently I got a requirement for printing using a Windows Service. The printing should be silent without any pop-up. Also I should be able to change the printer name and settings on the fly. I searched the internet and found some examples and finally two of them worked for me, so I am posting the working ones here.

There are two things that should be noted before we start:

  1. The User account should be used to execute a Windows Service. There are other accounts like Local System and Local service. I tried Local System but it doesn't work because the System Account doesn't obey our command to select a default printer. For system default printer is another then for a user (xps in my case).
  2. To allow the service to interact with the Desktop, if you are using a local system account, if your team wants you to use the Local System Account then in Windows XP, right-click on the service (after opening services.msc), open properties and choose this option "Allow to interact with Desktop". For the user account this option is not required.

First method 

The print document class provided by .NET is capable of printing inside a Windows Service. The benefit of using the print document class is that it gives some control of printing and settings. It exposes an event which can be consumed to change printing settings. 

Here's the code for this:

Namespace WindowsFormsApplication1

{

    public static class myPrinters

    {

        [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]

        public static extern bool SetDefaultPrinter(string Name);

    }

  public  class PrintDocumentMethod

    {

        private Font printFont;

        private Stream IOStream;

        private void pd_PrintPage(object sender, PrintPageEventArgs ev)

        {                        

            ev.Graphics.DrawImage(Image.FromStream(IOStream,true,false),ev.Graphics.VisibleClipBounds);

            ev.HasMorePages = false;

        }

        public void ChangeDefaultPrinter(String pname)

        {

            myPrinters.SetDefaultPrinter(pname);

        }

        public void Printing(string pname)

        {

            try

            {

                IOStream = new FileStream("C:\\scanned.jpeg", FileMode.Open, FileAccess.Read);

                //streamToPrint = new StreamReader(IOStream);

                try

                {

                    printFont = new Font("Arial", 10);

                    PrintDocument pd = new PrintDocument();

                    pd.PrintPage += new PrintPageEventHandler(pd_PrintPage);

                    // Specify the printer to use.

                    pd.PrinterSettings.PrinterName = pname;

                    pd.Print();

                }

                finally

                {

                    IOStream.Close();

                }

            }

            catch (Exception ex)

            {

              EventLog e =  new EventLog("Print Error");

              e.WriteEntry("Failed in Printing, Reason:" + ex.Message);

            }

        }

    }

}

Second Method

While searching I came across a second method for printing. This method uses creation of a process using System.Diagnostics.Process and start this process for printing. This code is quite small and can be used where the page settings are not required to be done, as this doesn't provide much control of printer settings.

class ProcessSpawnMethod

{

    public void Print()

    {

        //PrintDialog printDialog1 = new PrintDialog();

        //printDialog1.PrinterSettings.PrinterName = "EasyCoder 91 DT (203 dpi)";

        System.Diagnostics.Process process = new System.Diagnostics.Process();

        process.Refresh();

        //process.StartInfo.Arguments = "EasyCoder 91 DT (203 dpi)";

        process.StartInfo.CreateNoWindow = true;

        process.StartInfo.Verb = "print";

        process.StartInfo.FileName = @"C:\\MyFile.txt";

        process.StartInfo.UseShellExecute = true;

        process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;

        process.Start();

    }

}


Windows Service
 
And here is the code for Windows Service, to test the above methods.

protectedoverride void OnStart(string[] args)
 {
       
//PrintDocumentMethod way----
        WindowsFormsApplication1.PrintDocumentMethod printDoc =new WindowsFormsApplication1.PrintDocumentMethod();
       
//printDoc.ChangeDefaultPrinter("SATO CG212");  // to change default printer.
        printDoc.Printing("SATO CG212");
       
//ProcessSpawnMethod---
        //ProcessSpawnMethod pspawn = new ProcessSpawnMethod();
        //pspawn.Print();
 }


I have written the above code, just to test the printing when the Windows Service starts. I am thinking to use a timer here which will execute the code again and again. For now this code will run only once.

Login to add your contents and source code to this article
post comment
     

Thanks

Posted by Varun Bansal Nov 08, 2012

Nice article.

Posted by Nishu Nov 07, 2012

Great Varun. Yes I have seen this kind of requests but never got a chance to work on one. Yes, I agree. It would be nice to setup a Timer to print some files or say a folder every 24 hrs or so. So, I can see it building a utility that will print everything in a folder everyday at mid night. Very useful.

Posted by Mahesh Chand Nov 07, 2012
COMMENT USING
PREMIUM SPONSORS
DynamicPDF™ product line allows you to dynamically generate PDF documents, merge PDF documents and add new content to existing PDF documents from within your applications.
Join a Chapter
SPONSORED BY
  • PDF reports have never been easier to create. With our included WYSIWYG Designer, you can layout your reports, set up your data source and let DynamicPDF ReportWriter do the rest.