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:
FlowDocument document = MyDocument;
var source = document as IDocumentPaginatorSource;
var documentPaginator = source.DocumentPaginator;
using (var printServer = new LocalPrintServer())
{
PrintQueue queue = printServer.GetPrintQueue(printerName);
XpsDocumentWriter docWriter = PrintQueue.CreateXpsDocumentWriter(queue);
// Print ticket - Approach 1
// PrintTicket printTicket = queue.DefaultPrintTicket.Clone();
// Print ticket - Approach 2
var printTicket = new PrintTicket
{
PageOrientation = PageOrientation.Landscape,
PageMediaSize = new PageMediaSize(PageMediaSizeName.ISOA4), // set size of media (paper)
};
documentPaginator.PageSize = new Size(document.PageWidth, document.PageHeight);
docWriter.Write(documentPaginator, printTicket);
}
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':
System.Printing.PrintQueueException: PrintTicket provider failed to bind to printer. Win32 error: -2147467231
at MS.Internal.Printing.Configuration.PTProvider..ctor(String deviceName, Int32 maxVersion, Int32 clientVersion)
at MS.Internal.Printing.Configuration.PTProviderBase.Create(String deviceName, Int32 maxVersion, Int32 clientVersion)
at System.Printing.PrintTicketManager..ctor(String deviceName, Int32 clientPrintSchemaVersion)
at System.Printing.PrintQueue.get_DefaultPrintTicket()
Using 'Print ticket - Approach 2':
Exception encountered: System.Printing.PrintQueueException: Fehler beim Binden des PrintTicket-Anbieters an den Drucker. Win32-Fehler: -2147467231
bei MS.Internal.Printing.Configuration.PTProvider..ctor(String deviceName, Int32 maxVersion, Int32 clientVersion)
bei MS.Internal.Printing.Configuration.PTProviderBase.Create(String deviceName, Int32 maxVersion, Int32 clientVersion)
bei System.Printing.PrintTicketManager..ctor(String deviceName, Int32 clientPrintSchemaVersion)
bei System.Printing.PrintQueue.get_UserPrintTicket()
bei System.Printing.PrintQueue.get_CurrentJobSettings()
bei System.Printing.PrintQueue.CreateSerializationManager(Boolean isBatchMode, Boolean mustSetJobIdentifier)
bei System.Windows.Xps.XpsDocumentWriter.BeginWrite(Boolean batchMode, Boolean asyncMode, Boolean setPrintTicketHandler, PrintTicket printTicket, PrintTicketLevel printTicketLevel, Boolean printJobIdentifierSet)
bei System.Windows.Xps.XpsDocumentWriter.Write(DocumentPaginator documentPaginator, PrintTicket printTicket)
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.
Here I'll keep for myself some related questions: Printing from a Windows Service, Printing from a Windows Service, http://social.msdn.microsoft.com/Forums/en-US/ieextensiondevelopment/thread/b74bd27d-1cc8-4fca-a6de-2cd1371cf3b7/,
Mildly related: Printing from a .NET Service,
edit:
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
edit2:
Interesting. When I tried a different printing code there is no error:
using (var printDocument = new PrintDocument())
{
printDocument.PrinterSettings.PrinterName = printerName;
printDocument.Print();
}
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.
edit3:
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.