7

我有一个用 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)

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

在这里,我将为自己保留一些相关问题: 从 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

编辑2:

有趣的。当我尝试不同的打印代码时没有错误:

using (var printDocument = new PrintDocument())
{
    printDocument.PrinterSettings.PrinterName = printerName;
    printDocument.Print();
}

不幸的是,这是一个使用 System.Drawing.Graphics 库的旧 GDI+ 代码,它与我的以 System.Windows.Media.Visual 对象形式生成分页文档的代码不兼容。所以我不能用它来打印我的文档,除非我想花两周的时间从头开始创建我的文档的分页。

编辑3:

这里有关于这个问题的讨论:http: //social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/96e7fc10-3f08-4808-b748-692e30377293 有一个“解决方法”可以使用“任何CPU的平台。这种解决方法确实有效(我试过了),但是当我的服务需要 x86 时,它在我的情况下不可用。我已通过我们公司联系了 MS 支持以找到真正的解决方案。

4

3 回答 3

2

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

于 2013-05-09T07:41:05.837 回答
2

http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/fdcfa0fa-50aa-4a61-be79-5b4c8f65fbf7/我们看到这已报告给 Microsoft 并确认为 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-4272-8D1D-FF9B966D75B0} (或您在系统上找到的相应值)
  4. 在此注册表项下,删除名称为“AccessPermission”、“LaunchPermission”和“RunAs”的条目

由于这是 Windows 中的错误,因此您无法在代码中修复它。解决方法可能会产生副作用,但到目前为止,我们还没有在我们的场景中看到任何副作用。

于 2014-02-04T19:45:34.380 回答
-1

我有从 Windows 服务打印的相同经验,但我的问题出在 Windows Server 2008 中,我认为这是因为 Windows 服务不具备此功能。我阅读了很多博客等,但没有找到任何解决方案。我终于找到了一种方法,该服务调用另一个 exe 使用 microsoft 任务库进行打印。

于 2013-04-08T13:18:48.833 回答