23

我现在正在处理一个项目,该项目涉及从另一个应用程序接收消息,格式化该消息的内容并将其发送到打印机。选择的技术是 C# windows 服务。我想,输出可以称为报告,但报告引擎不是必需的。一个简单的模板引擎,如 StringTemplate,甚至输出 HTML 的 XSLT 都可以。我遇到的问题是找到一种从服务打印这种输出的免费方法。由于它似乎可以工作,我正在使用 Microsoft 的 RDLC 制作一个原型,填充本地报告,然后将其作为图像呈现到内存流中,然后我将打印出来。问题是:

  • 多页打印将是一个大麻烦。
  • 仍然必须使用 PrintDocument 来打印内存流,这在 Windows 服务中不受支持(尽管它可能有效 - 原型还没有那么远)
  • 如果遇到的数据发生变化,我必须更改数据集和数据被反序列化到的类。坏坏坏。

有没有人不得不远程做这样的事情?有什么建议吗?我已经发布了一个关于在没有用户输入的情况下打印 HTML 的问题,在浪费了大约 3 天之后,我得出的结论是它无法完成,至少不能使用任何免费提供的工具。

感谢所有帮助。

编辑:我们使用 .NET 框架的 2.0 版。

4

11 回答 11

16

相信我,与购买第三方组件相比,您将花费更多的钱来为此搜索/开发解决方案。不要重新发明轮子并寻求付费解决方案。

打印是一个复杂的问题,我希望看到为此添加更好的框架支持的那一天。

于 2008-08-11T19:20:29.707 回答
10

从 Windows 服务打印真的很痛苦。它似乎工作......有时......但最后它不时崩溃或抛出异常,没有任何明确的原因。真是没救了。官方甚至不支持它,没有任何解释,也没有任何替代解决方案的建议。

最近,我遇到了这个问题,经过几次不成功的尝试和实验,我终于有了两个可行的解决方案:

  • 使用 Win32 API(例如在 C/C++ 中)编写您自己的打印 DLL,然后通过 P/Invoke 从您的服务中使用它(工作正常)
  • 编写您自己的打印 COM+ 组件,然后从您的服务中使用它。我最近成功地选择了这个解决方案(但它是第三方 COM+ 组件,不是自己编写的)它也工作得很好。
于 2008-08-11T19:01:49.170 回答
8

我已经做到了。这是A *的痛苦。问题是打印需要 GDI 引擎就位,这通常意味着您必须拥有桌面,该桌面仅在您登录时加载。如果您尝试从服务器上的服务执行此操作,那么你通常没有登录。

因此,首先您不能以普通服务用户身份运行,而是以具有交互式登录权限的真实用户身份运行。然后你必须调整服务注册表项(我现在忘记了,如果你真的感兴趣,我必须找到今晚我可以做的代码)。最后,你必须祈祷。

您最大的长期头痛将是打印驱动程序。如果您在没有登录用户的情况下作为服务运行,则某些打印驱动程序喜欢不时弹出对话框。当您的打印机碳粉用完时会发生什么?还是缺纸?驱动程序可能会弹出一个永远不会看到的对话框,并因为没有人登录而阻塞了打印机队列!

于 2008-10-07T14:21:02.707 回答
5

要回答您的第一个问题,这可能是相当直接的,具体取决于数据。我们有多种基于服务的应用程序可以完全满足您的要求。通常,我们解析传入的文件并将我们自己的 Postscript 或 PCL 包裹在它周围。如果您的布局相当简单,那么您可以使用一些非常基本的 PCL 代码对其进行包装,以提供您想要的字体/打印布局(我很乐意在此离线为您提供一些指导)。

如果您有一个打印就绪文件,您可以将其发送到共享的 UNC 打印机、直接发送到本地安装的打印机,甚至发送到设备的 IP(RAW 或 LPR 类型数据)。

但是,如果您要使用 PDF 路径,最简单的方法是将 PDF 输出发送到支持直接 PDF 打印的打印机(现在很多人都这样做了)。在这种情况下,您只需将 PDF 发送到设备并打印出来。

另一种选择是启动Ghostscript,它应该可以免费满足您的需求(检查许可,因为它们有几个不同的版本,一些 GNU,一些 GPL 等)并使用它内置的打印功能或简单地转换为 Postscript 并发送到装置。我在服务应用程序中使用过 Ghostscript 很多次,但不是一个超级粉丝,因为您基本上是在运行命令行应用程序来进行转换。话虽这么说,它是一个稳定的应用程序,确实倾向于优雅地失败

于 2008-10-07T14:08:40.157 回答
4

从服务打印是个坏主意。网络打印机是“按用户”连接的。您可以将服务标记为以特定用户身份运行,但我认为这是一种不好的安全做法。您也许可以连接到本地打印机,但在走这条路线之前我仍然会犹豫。

最好的选择是让服务存储数据并让用户启动的应用程序通过向服务请求数据来进行打印。或存储数据的公共位置,如数据库。

如果您需要定期打印数据,请通过任务计划程序设置任务事件。从服务启动进程需要知道用户名和密码,这也是不好的安全做法。

至于打印本身,使用第三方工具生成报告将是最简单的。

于 2008-08-11T22:08:57.963 回答
1

这可能不是您想要的,但是如果我需要快速而肮脏地进行此操作,我会:

  1. 创建一个单独的 WPF 应用程序(这样我就可以使用内置的文档处理)
  2. 为服务提供与桌面交互的能力(请注意,您实际上不必在桌面上显示任何内容,也无需登录即可使用)
  3. 让服务运行应用程序,并为其提供要打印的数据。

您可能还可以通过从服务运行的 Web 浏览器进行打印(尽管我建议您构建自己的 shell IE,而不是使用完整的浏览器)。

对于更详细(也是免费)的解决方案,您最好的选择可能是自己手动格式化文档(使用 GDI+ 为您进行布局)。这是乏味的、容易出错的、耗时的,并且在开发过程中浪费了大量的纸张,但也让您可以最大程度地控制打印机的内容。

于 2008-08-11T17:46:52.220 回答
1

如果您可以输出到发布脚本,一些打印机将打印任何通过 FTP 传输到其上某个目录的内容。

我们用它来克服我们大学向我们公开的打印学分,但如果您的服务输出到 ps,那么您可以将 ps 文件通过 ftp 传输到打印机。

于 2008-10-07T14:26:15.283 回答
1

We are using DevExpress' XtraReports to print from a service without any problems. Their report model is similar to that of Windows Forms, so you could dynamically insert text elements and then issue the print command.

于 2009-08-27T19:13:02.763 回答
0

我认为我们将走第三方路线。我喜欢 XSL -> HTML -> PDF -> 打印机流程... Winnovative 的HTML 到 PDF在第一部分看起来不错,但我遇到了一个寻找好的 PDF 打印解决方案的障碍...有什么建议吗?理想情况下,许可证将基于开发人员,而不是基于部署的运行时。

于 2008-08-11T20:38:25.293 回答
0

在回答您有关 PDF 打印的问题时,我还没有找到一个优雅的解决方案。我正在向 Adob​​e 发出“shell”,这是不可靠的,并且需要用户始终登录。为了解决这个特定问题,我要求将我们处理的文件(发票)格式化为多页 Tiff 文件,而不是使用本机 .NET 打印功能进行拆分和打印。Adobe 的立场似乎是“让用户在 Adob​​e Reader 中查看文件,他们可以点击打印”。无用。

我仍然热衷于找到一种生成可以从 Web 服务器输出的高质量报告的好方法……

于 2008-10-21T13:09:55.247 回答
0

根据 Yann Trevin 的回复,MS 不支持使用 System.Drawing.Printing 进行打印。但是,您也许可以使用新的、基于 WPF 的 System.Printing(我认为

于 2009-07-14T22:25:34.577 回答