Reputation: 2301
I have developed a windows service in C# which receives a PDF file via network and it needs to print it to a installed printer. I am using a library to do actual printing (HiQPdf). I tested it in mock up console application.
When I install and run the service under Local System Account, the library throws an exception of {"No printers are installed."} System.Drawing.Printing.InvalidPrinterException
I found this by running the service as debug and attach to service in visual studio in administrator mode.
If I specify a user account on that machine by going to properties of the service (accessing the services by typing services.msc) and on the Log on tab, I specify this account and user name and password of a current user which I am logged on, then service perfectly does the print
This approach now has the downside of the need for the user make this change on service properties and keep the password of user up to date which is not ideal.
Now my question is that, is there any way of running that windows service under Local system account or any other account system account and not user account which requires providing username and password for that account?
I also found the following article Printing from a Windows Service which suggests not use certain libraries in a windows service and load a user profile (which I guess requires user credentials), but does not suggest how to do it under Local system account.
It is also interesting that even under Local system account I can get the list of installed printers where it includes the mentioned required printer:
try
{
if (System.Drawing.Printing.PrinterSettings.InstalledPrinters.Count > 0)
{
string[] ar = new string[System.Drawing.Printing.PrinterSettings.InstalledPrinters.Count];
System.Drawing.Printing.PrinterSettings.InstalledPrinters.CopyTo(ar, 0);
System.IO.File.WriteAllLines(@"c:\Projects\list_of_printter.txt", ar);
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
The following code snippet actually does the print job:
try
{
var pdfPrinter = new PdfPrinter();
logger.LogInformation("Created pdf printer");
pdfPrinter.PrinterSettings.PrinterName = printerName;
pdfPrinter.SerialNumber = "MY_LICENSE";
pdfPrinter.SilentPrinting = true;
pdfPrinter.PageSettings.Margins.Bottom = 0;
pdfPrinter.PageSettings.Margins.Left = 0;
pdfPrinter.PageSettings.Margins.Right = 0;
pdfPrinter.PageSettings.Margins.Top = 0;
pdfPrinter.PageSettings.Landscape = true;
logger.LogInformation("About to print document");
pdfPrinter.PrintPdf(fileBytes);
logger.LogInformation("Document should be printed now");
}
catch (Exception e)
{
logger.LogError($"Error when printing. Exception: {e}. Message: {e.Message}");
throw;
}
Upvotes: 1
Views: 4768
Reputation: 8626
I just had pretty much the same problem but failed even earlier using Windows Service. My advice just don't use that Windows Service project type. Create a Console application and use NSSM - the Non-Sucking Service Manager to make it a service. Also install and uninstall of service is less painfull and has a GUI if you wan't.
The problem then is that the default printer is different. You have to set the default printer manually:
var settings = new PrinterSettings();
settings.PrinterName = "HPBF11E5 (HP OfficeJet 6950)";
var p = new PrintDocument();
p.PrinterSettings = settings; //set settings with new default printer
...
That way I even got it working using the LocalService account without the "Allow service to interact with desktop" option.
Upvotes: 0
Reputation: 11637
The System user has no printers installed and it cannot see the printers you as a user have installed.
To print to a network printer from a service as System, you need to install the printer as a local printer.
http://techgenix.com/AddSharedPrinterasaLocalPrinter/
I use this for a Widows service that prints PDFs as well.
Upvotes: 1