Портативный способ определения принтера - физический или виртуальный - PullRequest
6 голосов
/ 25 февраля 2011

Мне нужна функция прямого доступа к принтеру для моего веб-сайта с возможностью отличать физический принтер от виртуального принтера (файл).

Coupons.com имеет эту функцию через собственный двоичный файл, который должен быть установлен пользователем. Я бы предпочел избежать этого.

SmartSource.com делает это через апплет Java:

Smart Source Java Applet

Кто-нибудь знает, как это делается? Я немного покопался в этих API-интерфейсах Java и не вижу ничего, что позволяло бы вам определять физическое или виртуальное, кроме как смотреть на имя (которое может быть ошибочно идентифицировано). Было бы неплохо сделать это на Java, потому что я уже знаю, как писать Java-апплеты. В противном случае, есть ли способ сделать это во Flash или Silverlight?

Заранее спасибо.

РЕДАКТИРОВАТЬ: Заслуженная награда, присужденная Джейсон Сперске, который разработал элегантное решение. Спасибо тем, кто поделился идеями, а также тем, кто действительно исследовал решение SmartSource.com (например, Адриан).

Ответы [ 3 ]

6 голосов
/ 01 марта 2011

Хорошо, вот то, что я нашел до сих пор (это не исчерпывающий тест, но попытка решить его была забавной).кажется, что может быть некоторая помощь, если посмотреть, как работает метод validatePage () в классе PrinterJob.Кажется, что если задание принтера является виртуальным, то любая попытка установить ImageableArea страницы всегда будет возвращать значение, точно равное страницам по умолчанию ImageableArea, в то время как попытка того же самого на реальном принтере будет возвращать немного меньшие значения (для учетакрая бумаги, удерживаемые механикой принтера. Что помогает в этой проблеме, так это то, что если вы просто спросите принтер о его характеристиках по умолчанию перед вызовом validate, вы получите оптимистичный результат, и если вы сравните это с проверенным ответом, вы можете сделатьпростой тест if. Я написал некоторый код для этого, который, кажется, работает с принтерами изображений и реальными принтерами, которые у меня есть на рабочем столе (опять же, это не исчерпывающе, но это может послужить отправной точкой)

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 голос
/ 28 февраля 2011

Я знаю, как это сделать очень легко на Win32. Существует структура с именем PRINTER_INFO_2, которая имеет поле с именем pPortName. Вы можете сравнить его со строкой «FILE» и получить все очереди, которые подключены к порту «FILE». И вы также можете добавить больше логики для анализа других виртуальных принтеров. Эта структура заполняется Windows, когда вы вызываете GetPrinter с дескриптором принтера. Теперь вопрос в том, как это сделать в .NET. Я видел один способ, который использует маршаллинг. Я видел некоторые фрагменты кода в http://vbcity.com/forums/t/66183.aspx. Вы также можете посмотреть на взаимодействие C # с помощью pInvoke. http://pinvoke.net/default.aspx/Structures/PRINTER_INFO_2.html

Надеюсь, это поможет.

1 голос
/ 27 февраля 2011

Как вы говорите, кажется, есть способы собрать немного информации о принтере:

javax.print.attribute.standard.PrinterMakeAndModel выглядит многообещающе.

Запрещение файла: назначение на любом принтере и печать на любом принтере со словом PDF в марке и модели принтера, вероятно, охватит 90% случаев, судя по этому списку программного обеспечения для виртуальной печати, Вы реально не встретите ложных срабатываний и в слове PDF.

Если эта функция не идеальна, ваш клиент вряд ли заметит; у ваших конкурентов, вероятно, также есть какой-то ужасный удар, потому что они точно также знают, что эта функция больше «театр безопасности», чем реальная безопасность.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...