Printing by executing a process in a Windows Service
I have a Windows Service that needs to start a process to send a file to the printer (I found that solution there https://stackoverflow.com/a/4875755/1228738) . I do this using the Process.Start(). My problem is that nothing happens.
The service is actually installed on my developer machine (win7, x64). I tried installing it as LOCAL SYSTEM, NETWORK SERVICE, LOCAL SERVICE with the same result every time.
I tried those way of starting my process :
When I execute the same code in a winform application, everything works fine, the file is sent to the printer. But in the Windows Service, nothing happens.
I saw that post https://stackoverflow.com/a/6271309/1228738, which explains why I would not see the UI, that’s fine I don’t have any UI anyway. But as said in the comment section, a process with no user input should be OK. The process that I start don’t need any user input.
The only thing I can think of right now, is that because of session isolation (https://stackoverflow.com/a/5063750/1228738), the service can’t find any installed printers. Can that be the case ? If so, any suggestion how to work around that ? And if not, any idea of what’s wrong ?
EDIT #1
I tried running the service with my user account, and it’s working, so I guess my fears are confirmed. the users LOCAL SYSTEM and NETWORK SERVICE have no installed printers.
So I’ll refine my question a little bit. Is there a way for those account to access printers installed on the computer ?
EDIT #2
We finally decided that a user will be created for running that service and in that user accounts we’ll install the printer on which to print.
I guess this question can be closed now. Thank you all for your help.
Printing EMF from a Windows service
I have some code that prints a document using the System.Drawing.Printing namespace. This now needs to be moved into a windows service. The documentation states that this is not possible, which would support my findings so far (in that it doesn’t work). I’m working under the assumption that I can get this to work by using the System.Printing namespace instead.
Here is the code that I have so far:
So I want to pass myDoc to pq.AddJob() , but this doesn’t seem to be possible. Using System.Drawing.Printing it was possible to simply render this on a page by page basis in the PrintDocument.PrintPage event.
Is what I’m trying to do possible, and if so, could someone point me in the right direction?
3 Answers 3
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.
It is important to understand what «not supported» means in this context. It literally means what it says, it you try to print from a service and discover a problem then you cannot call Microsoft Support and ask for help.
This is not a problem that’s induced by System.Drawing, it is a generic problem with printer drivers. Chunks of code that are supplied by the printer manufacturer, not Microsoft. A significant problem with them is that they are invariably designed to be used from a desktop program. Word, Acrobat, etcetera. They readily take advantage of that, they often pop up a window to let you know that they are Working On It. Not in the least to spam the manufacturer name and reminding you that the toner cartridge is half empty. These drivers are likely to misbehave in a service. The «runtime exceptions» phrase mentioned in the note.
The worst problem with them is that they use a popup window to let you know that there’s a problem. These windows are not visible when you use the printer driver from a service. So you’ll have to deal with print jobs that for no discernible reason refuse to print. The «diminished service performance» phrase in the note. That’s very difficult to deal with, IT staff is just powerless to have a shot at fixing the problem when they can’t see any diagnostic.
Your approach doesn’t solve that fundamental problem. If you really want to pursue this then contact the printer manufacturer and ask for specific advise. Don’t get your hopes up, getting good answers out of hardware companies is pretty difficult.
Printing from windows service on windows 8 fails
I have a windows service application written in C# .NET. This application is used to generate a report pdf by printing document to local software printer that generates PDFs. This works well on Windows XP and Windows 7. Unfortunately I found that on Windows 8 it fails. Then I found out that printing to any (even physical) printer on Windows 8 fails when I print from my service. What is missing in my program to work? I’m printing this way:
Service is set to ‘system account’ without ‘interacting with desktop’ (but I tried that too or to login as local user).
This results into exception on Windows 8. When using ‘Print ticket — Approach 1’:
Using ‘Print ticket — Approach 2’:
I would say that service is able to find those printers because when I have tried to print to non-existing printer and I got «invalid printer name» exception.
In case someone is interested in trying — here is my sample service application that tries to print simple document to printer selected in config file: http://bin.mypage.sk/FILES/PrintTestService.rar
Interesting. When I tried a different printing code there is no error:
Unfortunately this is a older GDI+ code using the System.Drawing.Graphics library which is not compatible with my code that produces paginated document in form of System.Windows.Media.Visual objects. So I can’t use it to print my document unless I’d like to spend two weeks of creating the pagination of my document from scratch.
There is discussion about this issue here: http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/96e7fc10-3f08-4808-b748-692e30377293 There is a ‘workaround’ for it to use ‘anyCPU’ platform. This workaround really works (I tried it) but it is not usable in my case when my service needs to be x86. I have contacted MS support through our company to find a real solution.
3 Answers 3
At http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/fdcfa0fa-50aa-4a61-be79-5b4c8f65fbf7/ we see that this was reported to Microsoft and confirmed as a bug in Windows 8 and Windows Server 2012.
This bug is triggered when trying to print from a 32bit process in non-standard user session (like e.g. a service).
According to Microsoft, this a bug was resolved in Windows 8.1 and Windows Server 2012 R2. However, we could still reproduce it on Windows 8.1.
On the same site, a workaround is given by Microsoft. This workaround solved the problem for us on Windows 8.1. It probably also works on Windows 8 and Windows Server 2012.
The workaround goes as follows:
Open Regedit and go to HKEY_CLASSES_ROOT\CLSID
Check the value of the «AppID» Registry Entry. In our case this was
Since this is a bug in Windows, you cannot fix it in your code. The workaround might have side effects, but we haven’t seen any so far in our scenario.
Solution: To wait for Microsoft to fix this bug. I have reported the bug (REG:113040910349062), they have confirmed it, but fix won’t be soon (in next months) and there is no date specified for it.
Workaround that we use: Create a small application that handles the printing, compile it as ‘anyCPU’ application and run it from service application (which I can’t compile as ‘anyCPU’ — I need ‘x86’ because of its dependencies). This workaround was tested and works. But it is dirty + causes overhead + extra care.
Edit: Microsoft provides a hotfix that should fix this problem in Windows 8 : http://support.microsoft.com/kb/2872151/EN-US ( «You cannot print from a 32-bit WPF application in an x64-based version of Windows 8 or Windows Server 2012» )
Edit (2013-11-04): we have tested the hotfix and it does not work on Windows 8 or Windows 8.1. Currently we are again in a phase of communicating with Microsoft.
Edit (2014-beginning of the year): we have received a response from Microsoft that they don’t know how to fix this bug and the bug is closed. So only solution for us at the moment is having a small app exe compiled as AnyCPU which is called by our x86 service. This approach works, but causes slowdown and our product is also harder to maintain because of this.
How to print PDF document from Windows Service
I have windows service that must periodically print PDF document from server. My function is
When I implement this in Windows Application it works, but when I implement in Windows service it does not work.
Can you help me?
3 Answers 3
I solved problem with Session 0. I use this class:
Now, my function look like:
Also, ServiceProcessInstaller must have `Account set to «LocalSystem». When I created service I set to «Local service» with this user it does not work. I did not try with «Network service» or «User».
I solved this problem with the registry edits found in this article: https://support.microsoft.com/en-us/kb/184291.
Printing from Windows services (and also IIS) uses the SYSTEM account as I understand it. This account does not have access to the printer but these registry edits gives that SYSTEM account printing privileges.
Here is a summary:
- export 3 keys («folders within regedit.exe») to .reg files:
- HKEY_CURRENT_USER\Software\Microsoft\Windows NT\Current Version\Devices
- HKEY_CURRENT_USER\Software\Microsoft\Windows NT\Current Version\PrinterPorts
- HKEY_CURRENT_USER\Software\Microsoft\Windows NT\Current Version\Windows
- edit your 3 newly created reg files and change «HKEY_CURRENT_USER» to «HKEY_USERS\.DEFAULT»
- run your 3 reg files by double clicking them in explorer (this adds them to the registry)
That’s all it takes. This helped me to print pdf files to a printer from PHP in IIS 7. My php script would work just fine so long as the server happened to have the Administrator logged in when the script was run. Now no one needs to be logged in and the script still works 🙂
I hope this saves someone as much searching and tinkering as I put in to find it.
printing a PDF file in a C# windows service under Local system account
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:
The following code snippet actually does the print job: