简体   繁体   English

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

[英]Printing from windows service on windows 8 fails

I have a windows service application written in C# .NET. 我有一个用C#.NET编写的Windows服务应用程序。 This application is used to generate a report pdf by printing document to local software printer that generates PDFs. 此应用程序用于通过将文档打印到生成PDF的本地软件打印机来生成报告pdf。 This works well on Windows XP and Windows 7. Unfortunately I found that on Windows 8 it fails. 这在Windows XP和Windows 7上运行良好。不幸的是我发现在Windows 8上它失败了。 Then I found out that printing to any (even physical) printer on Windows 8 fails when I print from my service. 然后我发现当我从我的服务打印时,打印到Windows 8上的任何(甚至物理)打印机都会失败。 What is missing in my program to work? 我的计划中缺少什么工作? I'm printing this way: 我是这样打印的:

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);
}

Service is set to 'system account' without 'interacting with desktop' (but I tried that too or to login as local user). 服务设置为“系统帐户”而没有“与桌面交互”(但我也尝试过或以本地用户身份登录)。

This results into exception on Windows 8. When using 'Print ticket - Approach 1': 这导致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()

Using 'Print ticket - Approach 2': 使用'打印票 - 方法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)

I would say that service is able to find those printers because when I have tried to print to non-existing printer and I got "invalid printer name" exception. 我会说服务能够找到那些打印机,因为当我尝试打印到不存在的打印机时,我得到“无效的打印机名称”异常。

Here I'll keep for myself some related questions: 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/ , 在这里,我将为自己保留一些相关问题: 从Windows服务 打印,从Windows服务打印http://social.msdn.microsoft.com/Forums/en-US/ieextensiondevelopment/thread/b74bd27d-1cc8-4fca -a6de-2cd1371cf3b7 /

Mildly related: Printing from a .NET Service , 温和相关: 从.NET服务打印

edit: 编辑:

In case someone is interested in trying - here is my sample service application that tries to print simple document to printer selected in config file: http://bin.mypage.sk/FILES/PrintTestService.rar 如果有人有兴趣尝试 - 这是我的示例服务应用程序,它试图将简单文档打印到配置文件中选择的打印机: http//bin.mypage.sk/FILES/PrintTestService.rar

edit2: EDIT2:

Interesting. 有趣。 When I tried a different printing code there is no error: 当我尝试不同的打印代码时,没有错误:

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

Unfortunately this is a older GDI+ code using the System.Drawing.Graphics library which is not compatible with my code that produces paginated document in form of System.Windows.Media.Visual objects. 不幸的是,这是使用System.Drawing.Graphics库的较旧的GDI +代码,该库与我的代码不兼容,该代码以System.Windows.Media.Visual对象的形式生成分页文档。 So I can't use it to print my document unless I'd like to spend two weeks of creating the pagination of my document from scratch. 因此我不能用它来打印我的文档,除非我想花两周时间从头开始创建我的文档分页。

edit3: EDIT3:

There is discussion about this issue here: http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/96e7fc10-3f08-4808-b748-692e30377293 There is a 'workaround' for it to use 'anyCPU' platform. 这里有关于这个问题的讨论: http//social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/96e7fc10-3f08-4808-b748-692e30377293有一个'解决方法'供它使用' anyCPU'平台。 This workaround really works (I tried it) but it is not usable in my case when my service needs to be x86. 这个解决方法确实有效(我试过了),但是当我的服务需要是x86时,它不适用于我的情况。 I have contacted MS support through our company to find a real solution. 我已经通过我们的公司联系了MS支持,以找到真正的解决方案。

Solution: To wait for Microsoft to fix this bug. 解决方案:等待Microsoft修复此错误。 I have reported the bug (REG:113040910349062), they have confirmed it, but fix won't be soon (in next months) and there is no date specified for it. 我已经报告了这个错误(REG:113040910349062),他们已经确认了,但修复不会很快(在接下来的几个月内)并且没有为它指定日期。

Workaround that we use: Create a small application that handles the printing, compile it as 'anyCPU' application and run it from service application (which I can't compile as 'anyCPU' - I need 'x86' because of its dependencies). 我们使用的解决方法:创建一个处理打印的小应用程序,将其编译为'anyCPU'应用程序并从服务应用程序运行它(我无法编译为'anyCPU' - 因为它的依赖性我需要'x86')。 This workaround was tested and works. 此解决方法已经过测试并且有效。 But it is dirty + causes overhead + extra care. 但它很脏+导致开销+额外的护理。

Edit: Microsoft provides a hotfix that should fix this problem in Windows 8 : http://support.microsoft.com/kb/2872151/EN-US ( "You cannot print from a 32-bit WPF application in an x64-based version of Windows 8 or Windows Server 2012" ) 编辑:Microsoft提供了一个修补程序,可以解决Windows 8中的此问题: http//support.microsoft.com/kb/2872151/EN-US (“您无法从基于x64的版本中的32位WPF应用程序打印的Windows 8或Windows Server 2012“)

Edit (2013-11-04): we have tested the hotfix and it does not work on Windows 8 or Windows 8.1. 编辑(2013-11-04):我们已经测试了此修补程序,它在Windows 8或Windows 8.1上不起作用。 Currently we are again in a phase of communicating with Microsoft. 目前,我们再次处于与微软沟通的阶段。

Edit (2014-beginning of the year): we have received a response from Microsoft that they don't know how to fix this bug and the bug is closed. 编辑(2014年 - 年初):我们收到了微软的回复,他们不知道如何解决这个错误并且错误已经关闭。 So only solution for us at the moment is having a small app exe compiled as AnyCPU which is called by our x86 service. 因此,目前只有我们的解决方案是将一个小的app exe编译为AnyCPU,由我们的x86服务调用。 This approach works, but causes slowdown and our product is also harder to maintain because of this. 这种方法有效,但会导致速度减慢,因此我们的产品也难以维护。

At http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/fdcfa0fa-50aa-4a61-be79-5b4c8f65fbf7/ we see that this was reported to Microsoft and confirmed as a bug in Windows 8 and Windows Server 2012. http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/fdcfa0fa-50aa-4a61-be79-5b4c8f65fbf7/,我们看到这是向Microsoft报告并确认为Windows 8和Windows Server中的错误2012。

This bug is triggered when trying to print from a 32bit process in non-standard user session (like eg a service). 尝试在非标准用户会话(例如服务)中从32位进程打印时会触发此错误。

According to Microsoft, this a bug was resolved in Windows 8.1 and Windows Server 2012 R2. 根据微软的说法,这个错误在Windows 8.1和Windows Server 2012 R2中得到了解决。 However, we could still reproduce it on Windows 8.1. 但是,我们仍然可以在Windows 8.1上重现它。

On the same site, a workaround is given by Microsoft. 在同一网站上,Microsoft提供了一种解决方法。 This workaround solved the problem for us on Windows 8.1. 此解决方法在Windows 8.1上解决了我们的问题。 It probably also works on Windows 8 and Windows Server 2012. 它可能也适用于Windows 8和Windows Server 2012。

The workaround goes as follows: 解决方法如下:

  1. Open Regedit and go to HKEY_CLASSES_ROOT\\CLSID{BA7C0D29-81CA-4901-B450-634E20BB8C34} 打开Regedit并转到HKEY_CLASSES_ROOT \\ CLSID {BA7C0D29-81CA-4901-B450-634E20BB8C34}

  2. Check the value of the "AppID" Registry Entry. 检查“AppID”注册表项的值。 In our case this was {AA0B85DA-FDDF-4272-8D1D-FF9B966D75B0} 在我们的例子中,这是{AA0B85DA-FDDF-4272-8D1D-FF9B966D75B0}

  3. Now go to HKEY_CLASSES_ROOT\\AppID{AA0B85DA-FDDF-4272-8D1D-FF9B966D75B0} (or the respective value you found on your system) 现在转到HKEY_CLASSES_ROOT \\ AppID {AA0B85DA-FDDF-4272-8D1D-FF9B966D75B0}(或您在系统上找到的相应值)
  4. Under this registry key, delete the entries with the name "AccessPermission", "LaunchPermission" and "RunAs" 在此注册表项下,删除名称为“AccessPermission”,“LaunchPermission”和“RunAs”的条目

Since this is a bug in Windows, you cannot fix it in your code. 由于这是Windows中的错误,因此无法在代码中修复它。 The workaround might have side effects, but we haven't seen any so far in our scenario. 解决方法可能有副作用,但在我们的场景中我们还没有看到任何副作用。

i had the same experience printing from a windows service but my problem was in windows server 2008, i think its because windows services are not meant to have this functionalities. 我有同样的经验从Windows服务打印但我的问题是在Windows Server 2008,我认为它因为Windows服务并不意味着具有这种功能。 I read a lot of blogs etc and didn't finda ny solution. 我阅读了很多博客等,并没有找到解决方案。 i finally found a way in which the service invokes another exe to print using the microsoft task library. 我终于找到了一种方法,服务使用microsoft任务库调用另一个exe进行打印。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM