确定打印机的便携方式是物理的或虚拟的

我需要为我的网站提供直接打印机function,能够区分物理打印机和虚拟打印机(文件)。

Coupons.com通过本机二进制文件具有此function,必须由用户安装。 我宁愿避免这种情况。

SmartSource.com通过Java applet实现:

智能源Java小程序

有谁知道这是怎么做的? 我对Java API进行了一些挖掘,除了查看名称(看起来容易出现错误识别)之外,没有看到任何可以让你确定物理与虚拟的东西。 能够用Java做它会很好,因为我已经知道如何编写Java applet了。 如果做不到,有没有办法在Flash或Silverlight中执行此操作?

提前致谢。

编辑:杰森Sperske获得了当之无愧的奖励,他们制定了一个优雅的解决方案。 感谢那些分享想法的人,以及那些实际调查过SmartSource.com解决方案的人(比如Adrian)。

好的,这是我到目前为止所发现的(这不是一个详尽的测试,但尝试和解决这个问题一直很有趣)。 通过查看PrinterJob类中的validatePage()方法是如何工作的,似乎可能会有一些帮助。 似乎如果打印机作业是虚拟的,那么任何设置页面的尝试ImageableArea将始终返回一个完全等于默认页面ImageableArea的值,而尝试与真实打印机相同的值将返回略小的值(以考虑到打印机机制所持有的纸张边缘。这个问题的原因在于,如果您在调用validate之前询问打印机的默认特性,则会获得乐观的结果,如果将其与经过validation的响应进行比较,则可以执行以下操作:简单,如果测试。我已经写了一些代码,这似乎与我在桌面上的图像打印机和真正的打印机一起工作(同样这不是详尽的,但它可以作为一个起点)

import java.awt.print.*; import javax.print.PrintService; import javax.print.attribute.Attribute; public class DetectFilePrinter { public static void main(String[] args) { PrinterJob job = PrinterJob.getPrinterJob(); PrintService printer = job.getPrintService(); System.out.println("Printer Name:"+printer.getName()); System.out.println(printer.toString()); PageFormat page = job.defaultPage(); double default_width = page.getWidth(); double default_height = page.getHeight(); Paper paper = new Paper(); paper.setImageableArea(0, 0, Double.MAX_VALUE, Double.MAX_VALUE); page.setPaper(paper); PageFormat fixed_page = job.validatePage(page); double fixed_width = fixed_page.getImageableWidth(); double fixed_height = fixed_page.getImageableHeight(); //So far all of my tested "image printers" return the same //height and width after calling validatePage() if(default_height == fixed_height && default_width == fixed_width) { System.out.println("This looks like a \"image printer\""); } else { System.out.println("This looks like a \"real printer\""); } } } 

正如你所说,似乎有办法收集有关打印机的一些信息:

javax.print.attribute.standard.PrinterMakeAndModel看起来很有希望。

禁用文件:任何打印机上的目标,打印到打印机品牌和型号中带有PDF字样的任何打印机,可能会覆盖此虚拟打印软件列表中的 90%。 实际上,您也不会在PDF这个词上遇到误报。

如果此function不完美,您的客户不太可能注意到; 你的竞争对手可能也有一些可怕的kludge,因为他们也知道这个function更像是“安全战场”,而不是实际的安全性。

我知道如何在Win32上轻松完成。 有一个名为PRINTER_INFO_2的结构,它有一个名为pPortName的字段。 您可以将其与字符串“FILE”进行字符串比较,并获取连接到“FILE”端口的所有队列。 您可以类似地添加更多解析逻辑来检测其他虚拟打印机。 当您使用打印机句柄调用GetPrinter时,Windows将填充此结构。 现在的问题是如何在.NET中完成它。 我看到了一种使用编组的方法。 我在http://vbcity.com/forums/t/66183.aspx中看到了一些代码片段。 您还可以使用pInvoke查看C#interop。 http://pinvoke.net/default.aspx/Structures/PRINTER_INFO_2.html

希望这可以帮助。