我有一个用C#.NET编写的Windows服务应用程序。此应用程序用于通过将文档打印到生成PDF的本地软件打印机来生成报告pdf。这在Windows XP和Windows 7上运行良好。不幸的是我发现在Windows 8上它失败了。然后我发现当我从我的服务打印时,打印到Windows 8上的任何(甚至物理)打印机都会失败。 我的计划中缺少什么工作?我是这样打印的:
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);
}
服务设置为“系统帐户”而没有“与桌面交互”(但我也尝试过或以本地用户身份登录)。
这导致Windows 8出现异常。使用'打印票证 - 方法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)
我会说服务能够找到那些打印机,因为当我尝试打印到不存在的打印机时,我的“打印机名称无效”异常。
在这里,我将为自己保留一些相关问题: 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/,
温和相关: Printing from a .NET Service,
编辑:
如果有人有兴趣尝试 - 这是我的示例服务应用程序,它尝试将简单文档打印到在配置文件中选择的打印机: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对象的形式生成分页文档。所以我不能用它来打印我的文档,除非我想花两周时间从头开始创建我的文档的分页。
EDIT3:
此处讨论此问题:http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/96e7fc10-3f08-4808-b748-692e30377293 使用'anyCPU'平台有一个“解决方法”。这个解决方法确实有效(我试过了),但是当我的服务需要是x86时,它不适用于我的情况。我已通过我们公司联系MS支持人员,以找到真正的解决方案。
答案 0 :(得分:2)
解决方案:等待Microsoft修复此错误。我已经报告了这个错误(REG:113040910349062),他们已经确认了,但修复不会很快(在接下来的几个月内)并且没有为它指定日期。
我们使用的解决方法: 创建一个处理打印的小应用程序,将其编译为'anyCPU'应用程序并从服务应用程序运行它(我无法编译为'anyCPU' - 我需要'x86',因为它的依赖性)。此解决方法已经过测试并且有效。但它很脏+导致开销+额外的护理。
编辑:Microsoft提供了一个修补程序,可以解决Windows 8中的此问题:http://support.microsoft.com/kb/2872151/EN-US(“您无法从基于x64的Windows 8或Windows Server 2012版本中的32位WPF应用程序进行打印”)
编辑(2013-11-04):我们测试了此修补程序,它在Windows 8或Windows 8.1上不起作用。目前,我们再次处于与微软沟通的阶段。
编辑(2014年年初):我们收到了微软的回复,他们不知道如何修复此错误并且错误已关闭。因此,目前只有我们的解决方案是将一个小的app exe编译为AnyCPU,由我们的x86服务调用。这种方法有效,但会导致速度减慢,因此我们的产品也难以维护。
答案 1 :(得分:2)
在http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/fdcfa0fa-50aa-4a61-be79-5b4c8f65fbf7/我们看到这是向Microsoft报告的,并在Windows 8和Windows Server 2012中被确认为错误。
尝试在非标准用户会话(例如服务)中从32位进程进行打印时会触发此错误。
根据Microsoft的说法,这个错误在Windows 8.1和Windows Server 2012 R2中得到了解决。但是,我们仍然可以在Windows 8.1上重现它。
在同一网站上,Microsoft提供了一种解决方法。此解决方法在Windows 8.1上解决了我们的问题。它可能也适用于Windows 8和Windows Server 2012。
解决方法如下:
打开Regedit并转到HKEY_CLASSES_ROOT \ CLSID {BA7C0D29-81CA-4901-B450-634E20BB8C34}
检查“AppID”注册表项的值。在我们的案例中,这是{AA0B85DA-FDDF-4272-8D1D-FF9B966D75B0}
由于这是Windows中的一个错误,因此无法在代码中修复它。解决方法可能有副作用,但到目前为止我们还没有看到任何副作用。
答案 2 :(得分:-1)