确定打印机是物理还是虚拟的便携式方法
我的网站需要直接打印机功能,能够区分物理打印机和虚拟打印机(文件)。
Coupons.com 通过必须由用户安装的本机二进制文件来提供此功能。我宁愿避免这种情况。
SmartSource.com 通过 Java 小程序实现此操作:
有人知道这是如何完成的吗?我仔细研究了一下 Java API,没有看到任何可以让您确定物理与虚拟的东西,除了查看名称(这似乎很容易被误认)。如果能够用 Java 来做这件事那就太好了,因为我已经知道如何编写 Java 小程序了。如果做不到这一点,有没有办法在 Flash 或 Silverlight 中做到这一点?
提前致谢。
编辑: 贾森·斯佩斯克 (Jason Sperske) 获得了当之无愧的赏金,他制定了一个优雅的解决方案。感谢那些分享想法的人,以及那些真正研究过 SmartSource.com 解决方案的人(例如 Adrian)。
I need direct-to-printer functionality for my website, with the ability to distinguish a physical printer from a virtual printer (file).
Coupons.com has this functionality via a native binary which must be installed by the user. I'd prefer to avoid that.
SmartSource.com does it via Java applet:
Does anybody know how this is done? I dug through that Java APIs a bit, and don't see anything that would let you determine physical vs virtual, except looking at the name (that seems prone to misidentification). It would be nice to be able to do it in Java, because I already know how to write Java applets. Failing that, is there a way to do this in Flash or Silverlight?
Thanks in advance.
EDIT: Well deserved bounty awarded to Jason Sperske who worked out an elegant solution. Thanks to those of you who shared ideas, as well as those who actually investigated SmartSource.com's solution (like Adrian).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
好的,这是我到目前为止所发现的(无论如何,这都不是一个详尽的测试,但尝试解决它是一个有趣的问题)。通过查看 PrinterJob 类中的 validatePage() 方法的工作原理似乎可能会有所帮助。看起来,如果打印机作业是虚拟的,则任何设置页面 ImageableArea 的尝试都将始终返回与默认页面 ImageableArea 完全相同的值,而尝试对真实打印机设置相同的值将返回稍小的值(以考虑到解决这个问题的方法是,如果您在调用验证之前询问打印机的默认特性,您会得到一个乐观的结果,如果您将其与经过验证的响应进行比较,您可以执行以下操作:简单的 if 测试。我为此编写了一些代码,这些代码似乎适用于我桌面上的图像打印机和真实打印机(同样,这并不详尽,但它可以作为一个起点)
OK here is what I've found so far (this is not an exhaustive test by any means, but it has been a fun problem to try and tackle). it seems that there might be some help by looking at how the validatePage() method in the PrinterJob class works. It seems that if a printer job is virtual than any attempt to set a page's ImageableArea will always return a value exactly equal to the default pages ImageableArea while an attempt to to the same to a real printer will return slightly smaller values (to account for the edges of the paper being held by the printer mechanics. What helps for this problem is that if you just ask a printer for it's default characteristics before calling validate you get an optimistic result, and if you compare this to a validated response you can do a simple if test. I've written some code for this that seems to work with the image printers and real printers I have on my desktop (again this isn't exhaustive, but it could work as a starting point)
正如您所说,似乎有一些方法可以收集有关打印机的一些信息:
javax.print.attribute.standard.PrinterMakeAndModel
看起来很有希望。禁止文件:任何打印机上的目标,以及打印到打印机品牌和型号中带有
PDF
一词的任何打印机,根据 此虚拟打印软件列表。实际上,您也不会遇到 PDF 这个词的误报。如果此功能不完美,您的客户可能不会注意到;你的竞争对手可能也有一些可怕的拼凑,因为他们也知道这个功能更多的是“安全剧场”而不是实际的安全性。
As you say, there appear to be ways of gleaning a bit of information about the printer:
javax.print.attribute.standard.PrinterMakeAndModel
looks promising.Disallowing file: Destinations on any printer, and printing to any printer with the word
PDF
in the printer make and model would likely cover 90% of the cases judging by this list of virtual print software. You realistically aren't going to run into false positives on the word PDF either.If this feature isn't perfect, your client isn't likely to notice; your competitors likely also have some horrible kludge because they know just as well this feature is more "security theater" than actual security.
我知道如何在 Win32 上轻松地做到这一点。有一个名为 PRINTER_INFO_2 的结构,其中有一个名为 pPortName 的字段。您可以将其与字符串“FILE”进行字符串比较,并获取连接到“FILE”端口的所有队列。您还可以类似地添加更多解析逻辑来检测其他虚拟打印机。当您使用打印机句柄调用 GetPrinter 时,Windows 会填充此结构。现在的问题是如何在.NET 中做到这一点。我看到了一种使用编组的方法。我在 http://vbcity.com/forums/t/66183.aspx。您还可以使用 pInvoke 查看 C# 互操作。 http://pinvoke.net/default.aspx/Structures/PRINTER_INFO_2.html
希望这有帮助。
I know how to do it very easily on Win32. There is a structure called PRINTER_INFO_2 which has a field called pPortName. You can string compare it with the string "FILE" and get all the queues which are connected to the "FILE" port. And you can similarly add in more parsing logic for detecting other virtual printers. This structure is filled up by Windows when you call GetPrinter with the printer handle. Now the question is how to do it in .NET. I saw one way which is using marshalling. I saw some code snippets in http://vbcity.com/forums/t/66183.aspx. You can also look at C# interop using pInvoke. http://pinvoke.net/default.aspx/Structures/PRINTER_INFO_2.html
Hope this helps.