我的网站需要直接打印机功能,能够区分物理打印机和虚拟打印机(文件)。
Coupons.com通过本机二进制文件具有此功能,必须由用户安装。我宁愿避免这种情况。
SmartSource.com通过Java applet实现:
有人知道这是怎么做到的吗?我对Java API进行了一些挖掘,除了查看名称(似乎容易出现错误识别)之外,没有看到任何可以让您确定物理与虚拟的内容。能够用Java做它会很好,因为我已经知道如何编写Java applet了。如果做不到,有没有办法在Flash或Silverlight中执行此操作?
提前致谢。
编辑: Jason Sperske获得了当之无愧的奖励,他们制定了优雅的解决方案。感谢那些分享想法的人,以及那些实际调查过SmartSource.com解决方案的人(比如Adrian)。
答案 0 :(得分:6)
好的,这是我到目前为止所发现的(这不是一个详尽的测试,但尝试和解决这个问题一直很有趣)。通过查看PrinterJob类中的validatePage()方法是如何工作的,似乎可能会有一些帮助。似乎如果打印机作业是虚拟的,那么任何设置页面的尝试ImageableArea将始终返回一个完全等于默认页面ImageableArea的值,而尝试与真实打印机相同的值将返回略小的值(以考虑到打印机机制所持有的纸张边缘。这个问题的原因在于,如果您在调用验证之前只询问打印机的默认特性,您会得到一个乐观的结果,如果将其与经过验证的响应进行比较,您可以执行以下操作:简单,如果测试。我已经写了一些代码,这似乎与我在桌面上的图像打印机和真正的打印机一起工作(再次这不是详尽的,但它可以作为一个起点)
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\"");
}
}
}
答案 1 :(得分:1)
正如您所说,似乎有办法收集有关打印机的一些信息:
javax.print.attribute.standard.PrinterMakeAndModel
看起来很有希望。
禁止文件:任何打印机上的目标,打印到打印机品牌和型号中带有单词PDF
的任何打印机,可能会覆盖this list of virtual print software判断的90%的情况。实际上,你不会在PDF这个词上遇到误报。
如果此功能不完善,您的客户不太可能注意到;你的竞争对手可能也有一些可怕的kludge,因为他们也知道这个功能更像是“安全战场”,而不是实际的安全性。
答案 2 :(得分:1)
我知道如何在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
希望这有帮助。