Condividi tramite


打印机默认设置为letter而不是A4

这里的问题是在一个网络服务内通过业务连接器将X++报告打印成文件(pdf)时,默认纸张大小是”letter”而不是在常用的”A4”。我们先解释AX如何发现默认打印机,而后我们再谈如何应用到我们的问题。

AX内核如何发现默认打印机:

后台发生的是:AX内核调用Windows内核函数GetDefaultPrinter() (https://msdn.microsoft.com/en-us/library/dd144876(VS.85).aspx)。这个函数查找注册表项:

.. Software\Microsoft\Windows NT\CurrentVersion\Windows\Device,

要想知道默认打印机究竟是HKCU,HKU\UserSid 还是HKU\Default,取决于该函数运行时的环境和具体用户的配置文件是否存在。一旦这个内核函数从这里发现了打印设备,它将转换到另一个注册表项:

..Software\Microsoft\Windows NT\CurrentVersion\Devices\<printer name>

之后,AX内核使用Windows内核函数OpenPrinter() (https://msdn.microsoft.com/en-us/library/dd162751(VS.85).aspx)来获取打印机的属性——这时纸张大小会被确定。如果这个内核函数执行失败了,或者没有直接输出到打印设备(比如:输出到文件/屏幕等等),那么AX内核将使用默认设置来创建一个虚拟打印机,这样即使连接不到打印机也能让打印继续执行。这个虚拟打印机所用的默认纸张大小是”letter”,这就是”letter”出现的根源。

我们创建一个虚拟打印机的原因是在w3wp进程中运行业务连接器时,我们并不一定能得到打印机的信息。因此,作为新的.NET 业务连接器和企业门户框架的一部分,该机制包含在了AX4的开发中。如果缺少这个机制,在特定的配置下,报表引擎所依赖的底层打印功能有可能会失败。

为什么有时我们找不到默认打印机:

现在,如果我们呈现一个特殊的场景:比如我们可能在一个网络服务内执行一个业务连接器,它作为应用程序池标识来运行。 当我们调用内核函数GetDefaultPrinter()时,我们发现对于这个身份没有对应的用户配置文件(这不是因为访问被拒绝,而仅仅是因为它不存在)。这个现象可以通过Process Monitor工具中的类似于如下的一行追溯到:

12:34:23.5536848 PM w3wp.exe 2676 RegOpenKey HKU\S-1-5-82-2257762870-3033483361-1282393911-956591122-915368935 NAME NOT FOUND Desired Access: Read

下一步,我们跳转到默认用户配置文件。此文件是存在的,但是我们需要的键却不存在,这从根本上告诉我们默认用户配置文件没有对应的默认打印机:

12:34:23.5537105 PM w3wp.exe 2676 RegOpenKey HKU\.DEFAULT\Software\Microsoft\Windows NT\CurrentVersion\Windows NAME NOT FOUND Desired Access: Read

既然我们在上一步没有找到打印机,我们就不能返回一个默认打印机,所以当我们调用内核函数openPrinter()时我们也会失败,然后虚拟打印机就会被选择作为替代(虚拟打印机的纸张大小是”letter”而不是”A4”)。

为了解决这个问题,您需要用一个域帐号来运行应用程序池来保证它能找到一个真正的打印机。您可以用上文提到的工具Process Monitor来测试,查看查找打印机过程的每一步,这样可以找到哪一步失败了。

 

 

原文地址:

https://blogs.msdn.com/b/emeadaxsupport/archive/2011/04/27/printer-defaults-to-letter-instead-of-a4-how-ax-finds-the-default-printer.aspx