从Windows 8上的Windows服务打印失败

Mir*_*sik 7 c# windows printing service

我有一个用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);
}
Run Code Online (Sandbox Code Playgroud)

服务设置为"系统帐户"而没有"与桌面交互"(但我也尝试过或以本地用户身份登录).

这导致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()
Run Code Online (Sandbox Code Playgroud)

使用'打印票 - 方法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)
Run Code Online (Sandbox Code Playgroud)

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

在这里,我会继续为我自己的一些相关问题: 从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();
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,这是使用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支持,以找到真正的解决方案.

Nin*_*rry 3

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 上重现它。

在同一站点上,微软提供了一种解决方法。此解决方法为我们解决了 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 中的错误,因此您无法在代码中修复它。该解决方法可能会产生副作用,但到目前为止,我们在场景中还没有看到任何副作用。