从.NET服务打印

时间:2020-03-05 18:39:00  来源:igfitidea点击:

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

  • 多页打印将是一个很大的麻烦。
  • 仍然必须使用PrintDocument来打印内存流,这是Windows服务不支持的(尽管它可以工作-原型还没有到此为止)
  • 如果遇到的数据发生变化,则必须更改数据集以及将数据反序列化为的类。坏坏坏。

有人有做过这样的事情吗?有什么建议吗?我已经提出了一个关于在没有用户输入的情况下打印HTML的问题,在浪费了大约3天的时间之后,我得出的结论是,至少使用任何免费工具都无法做到这一点。

感谢所有帮助。

编辑:我们在.NET框架的2.0版上。

解决方案

回答

这可能不是我们要的内容,但是如果我需要快速又脏的话,我会:

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

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

对于更详细(也是免费的)解决方案,最好的选择是自己手动设置文档格式(使用GDI +进行布局)。这是繁琐的,容易出错的,耗时的,并且在开发过程中浪费了很多纸张,而且还使我们可以最大程度地控制打印机的输出。

回答

从Windows服务进行打印确实很痛苦。它似乎可以正常工作……有时……但是最终它会在没有任何明确原因的情况下不时地发出紧急信号或者抛出异常。真的没有希望了。正式地,甚至没有任何解释,也没有任何替代解决方案的建议,甚至不受支持。

最近,我遇到了这个问题,经过几次失败的试验和尝试,我终于找到了两个可行的解决方案:

  • 使用Win32 API(例如,在C / C ++中)编写自己的打印DLL,然后通过P / Invoke从服务中使用它(可以正常工作)
  • 编写自己的打印COM +组件,然后从服务中使用它。我最近成功选择了该解决方案(但它是第三方COM +组件,而不是自己编写的),它也绝对可以正常工作。

回答

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

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

回答

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

回答

从服务打印是一个坏主意。网络打印机是"按用户"连接的。我们可以将服务标记为以特定用户身份运行,但是我认为这是一种不良的安全做法。我们也许可以连接到本地打印机,但是在进行此操作之前,我仍然会犹豫。

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

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

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

回答

为了回答第一个问题,根据数据,这可能很简单。我们有各种各样的基于服务的应用程序可以完全满足要求。通常,我们解析传入的文件,并在其周围包装我们自己的Postscript或者PCL。如果布局非常简单,那么可以打包一些非常基本的PCL代码,以提供所需的字体/打印布局(我很乐意在离线提供一些指导)。

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

但是,如果我们沿着PDF路径前进,最简单的方法是将PDF输出发送到支持直接PDF打印的打印机(现在很多)。在这种情况下,我们只需将PDF发送到设备并打印即可。

另一种选择是启动Ghostscript,它应根据需求免费提供(请检查许可,因为它们具有一些不同的版本,一些GNU,一些GPL等),并可以使用它的内置打印功能,也可以简单地转换为Postscript并发送到装置。我已经在Service应用程序中使用Ghostscript多次,但并不是一个忠实的拥护者,因为我们基本上会掏空并执行命令行应用程序来进行转换。话虽这么说,这是一个稳定的应用,确实​​会优雅地失败

回答

我做完了这是A * s的痛苦。问题是打印需要安装GDI引擎,这通常意味着我们必须拥有台式机,该台式机只能在登录时加载。如果我们尝试通过服务器上的服务执行此操作,那么我们通常不会登录。

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

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

回答

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

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

回答

在回答有关PDF打印的问题时,我还没有找到一个好的解决方案。我当时向外壳"求助",这是不可靠的,需要用户始终登录。为了解决此特定问题,我要求将我们处理的文件(发票)格式化为多页Tiff文件,而不是可以拆分并使用本机.NET打印功能进行打印。 Adobe的立场似乎是"让用户在Adobe Reader中查看文件,然后他们可以单击打印"。无用。

我仍然很想找到一种产生质量报告的好方法,该报告可以从Web服务器输出...

回答

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

回答

我们正在使用DevExpress的XtraReports从服务中进行打印,而没有任何问题。他们的报告模型与Windows窗体的报告模型相似,因此我们可以动态插入文本元素,然后发出print命令。