我有一个用C#.NET编写的Windows服务应用程序。 此应用程序用于生成报告pdf通过打印文档到本地生成PDF的软件打印机。 这在Windows XP和Windows 7上运行良好。不幸的是我发现在Windows 8上它失败了。 然后,我发现打印到Windows 8上的任何(甚至是物理)打印机在从我的服务打印时都失败。 我的程序中缺less什么工作? 我这样打印:
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); }
服务设置为“系统帐户”,而不与“与桌面交互”(但我也尝试过,或以本地用户身份login)。
这在Windows 8上会导致exception。使用“打印票据 – 方法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()
使用“打印票 – 方法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)
我会说,服务是能够find这些打印机,因为当我已经试图打印到不存在的打印机,我有“无效的打印机名称”例外。
在这里,我将保留一些相关的问题: 从Windows服务 打印,从Windows服务打印 , http://social.msdn.microsoft.com/Forums/en-US/ieextensiondevelopment/thread/b74bd27d-1cc8-4fca -a6de-2cd1371cf3b7 / ,
轻微相关: 从.NET服务打印 ,
编辑:
如果有人有兴趣尝试 – 这里是我的示例服务应用程序,试图打印简单的文件到打印机中select的configuration文件: http : //bin.mypage.sk/FILES/PrintTestService.rar
EDIT2:
有趣。 当我尝试不同的打印代码时,没有错误:
using (var printDocument = new PrintDocument()) { printDocument.PrinterSettings.PrinterName = printerName; printDocument.Print(); }
不幸的是,这是一个使用System.Drawing.Graphics库的较旧的GDI +代码,它与我的代码不兼容,以System.Windows.Media.Visual对象的forms生成分页文档。 所以我不能用它来打印我的文档,除非我想花两个星期从头开始创build我的文档的分页。
EDIT3:
这里有关于这个问题的讨论: http : //social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/96e7fc10-3f08-4808-b748-692e30377293有一个“解决方法”,它使用“任何CPU“平台。 这个解决方法真的有效(我试过了),但是当我的服务需要x86的时候,这种方法是不可用的。 我已经通过我们的公司与MS支持联系,寻找真正的解决scheme。
在http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/fdcfa0fa-50aa-4a61-be79-5b4c8f65fbf7/我们看到,这是向微软报告,并确认为Windows 8和Windows server中的错误2012。
尝试从非标准用户会话中的32位进程打印时(例如服务)触发此错误。
据微软称,这个bug在Windows 8.1和Windows server 2012 R2中得到了解决。 但是,我们仍然可以在Windows 8.1上重现它。
在同一个网站上,Microsoft提供了一个解决方法。 这个解决方法解决了我们在Windows 8.1上的问题。 它可能也适用于Windows 8和Windows server 2012。
解决方法如下:
打开注册表并转到HKEY_CLASSES_ROOT \ CLSID {BA7C0D29-81CA-4901-B450-634E20BB8C34}
检查“AppID”注册表项的值。 在我们的情况下,这是{AA0B85DA-FDDF-4272-8D1D-FF9B966D75B0}
由于这是Windows中的一个错误,因此无法在代码中修复它。 解决方法可能有副作用,但是我们目前还没有看到我们的情况。
解决方案:等待Microsoft修复此错误。 我已经报告了这个错误(REG:113040910349062),他们已经确认了,但是修复不会很快(在接下来的几个月),并且没有指定日期。
我们使用的解决方法:创建一个处理打印的小应用程序,将其编译为“anyCPU”应用程序并从服务应用程序运行(我无法编译为“anyCPU” – 由于它的依赖关系我需要“x86”)。 此解决方法已经过测试并可以正常工作。 但它很脏+会造成额外的开销+额外的照顾。
编辑:Microsoft提供了一个修复程序应该可以解决此问题在Windows 8中: http : //support.microsoft.com/kb/2872151/EN-US (“您不能从基于x64的版本中的32位WPF应用程序打印Windows 8或Windows server 2012的“)
编辑(2013-11-04):我们已经测试了此修补程序,它不能在Windows 8或Windows 8.1上运行。 目前我们又处于与微软沟通的阶段。
编辑(2014年 – 今年年初):我们收到微软的回应,他们不知道如何解决这个错误,并且错误已经关闭。 因此,目前我们唯一的解决方案是将一个小型的应用程序exe编译为我们的x86服务调用的AnyCPU。 这种方法是有效的,但是会导致放缓,而且我们的产品也因此而难以维护。
我有从Windows服务打印相同的经验,但我的问题是在Windows server 2008中,我认为它是因为Windows服务并不意味着有这个功能。 我读了很多博客等,并没有找到任何解决方案。 我终于找到了一种方法,其中服务调用另一个EXE打印使用微软任务库。