在windows 8上从windows服务打印失败

本文关键字:windows 打印 失败 服务 上从 | 更新日期: 2023-09-27 18:07:52

我有一个用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上出现异常。当使用"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()

使用'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)

我会说服务能够找到这些打印机,因为当我试图打印到不存在的打印机时,我得到了"无效的打印机名称"异常。

在这里,我将保留一些相关的问题:从Windows服务中打印,从Windows服务中打印,http://social.msdn.microsoft.com/Forums/en-US/ieextensiondevelopment/thread/b74bd27d-1cc8-4fca-a6de-2cd1371cf3b7/

轻度相关:从。net服务打印,

编辑:

如果有人有兴趣尝试-这是我的示例服务应用程序,试图打印简单的文档到配置文件中选择的打印机: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支持,寻求真正的解决方案。

在windows 8上从windows服务打印失败

在http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/fdcfa0fa-50aa-4a61-be79-5b4c8f65fbf7/我们看到这是报告给微软,并确认为Windows 8和Windows Server 2012的错误。

当尝试在非标准用户会话(如服务)中从32位进程打印时触发此错误。

根据微软的说法,这个错误在Windows 8.1和Windows Server 2012 R2中得到了解决。但是,我们仍然可以在Windows 8.1上复制它。

在同一站点上,Microsoft提供了一个解决方案。这个解决方案解决了我们在Windows 8.1上的问题。它可能也适用于Windows 8和Windows Server 2012。

解决方法如下:

  1. 打开Regedit并进入HKEY_CLASSES_ROOT'CLSID{BA7C0D29-81CA-4901-B450-634E20BB8C34}

  2. 查看"AppID"注册表项值。在我们的例子中,这是{AA0B85DA-FDDF-4272-8D1D-FF9B966D75B0}

  3. 现在转到HKEY_CLASSES_ROOT'AppID{aa0b85da - fddf - 4277 - 8d1d - ff9b966d75b0}(或您在系统上找到的相应值)
  4. 在此注册表项下,删除名称为"AccessPermission","LaunchPermission"answers"RunAs"的条目

由于这是Windows中的一个错误,您无法在代码中修复它。这个变通方法可能有副作用,但是到目前为止我们还没有看到任何副作用。

解决方案:等待微软修复此错误。我已经报告了这个bug (REG:113040910349062),他们已经确认了这个bug,但是修复不会很快(在下个月),也没有指定修复的日期。

我们使用的解决方案:创建一个处理打印的小应用程序,将其编译为'anyCPU'应用程序,并从服务应用程序运行它(我不能将其编译为'anyCPU' -我需要'x86',因为它的依赖性)。此解决方案经过测试并有效。但是它是脏的+引起开销+额外的小心。

编辑:微软提供了一个热修复程序,应该可以解决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年初):我们收到了微软的回复,他们不知道如何修复这个bug,这个bug已经关闭了。所以我们目前唯一的解决方案是有一个小的应用程序exe编译为AnyCPU,由我们的x86服务调用。这种方法是有效的,但会导致速度变慢,因此我们的产品也更难维护。

我在Windows服务中有同样的打印经验,但我的问题是在Windows server 2008中,我认为这是因为Windows服务并不意味着有这个功能。我读了很多博客等,没有找到我的解决方案。我最终找到了一种方法,该服务调用另一个exe来使用Microsoft任务库进行打印。