Как преобразовать драйвер принтера в автономное консольное приложение, которое может генерировать файл принтера, содержащий байты для отправки на принтер? - PullRequest
14 голосов
/ 22 апреля 2010

У меня есть ситуация, когда только способ создать определенный файл данных - это распечатать его вручную в файл: в Windows и сохранить его в файле для дальнейшей обработки.

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

Возможно ли это с подходящим Windows SDK?Я программист на Java, поэтому я не знаю Visual Studio и возможностей с MSDN - пока!- но я был бы признателен за указатели.


РЕДАКТИРОВАТЬ: У меня есть установочные файлы для этого драйвера принтера, как 32-разрядных, так и 64-разрядных.Более старые версии могут включать 16-битный драйвер.


РЕДАКТИРОВАТЬ: функциональность «print to FILE:» - это то, что было рекомендовано в документации.Я немного поиграл с использованием LPR-протокола, чтобы посмотреть, на что он способен.Я все еще предпочел бы подход "вызвать небольшой двоичный файл".

Ответы [ 7 ]

12 голосов
/ 02 мая 2010

Общую проблему, которую вы формулируете, трудно решить. В основном драйвер принтера состоит из некоторых хорошо известных компонентов, таких как Print Monitor, Print Processor и т. Д., Которые хорошо документированы в Windows Driver Kit http://msdn.microsoft.com/en-us/library/ff560885%28v=VS.85%29.aspx. Несколько лет назад я написал Print Monitor. Он работал много лет на клиента. Так что я точно знаю, о чем пишу. Монитор печати - это не более, чем DLL с хорошо документированными функциями. То же самое касается большинства других компонентов принтера. Эти DLL будут загружены и вызваны из Spooler. Если у вас есть современный драйвер принтера, он не имеет компонентов, которые работают в режиме ядра. Таким образом, можно загрузить большинство библиотек DLL, из которых состоит каждый драйвер принтера, и вызвать соответствующую функцию .

.

Вам интересно использовать один драйвер концертного принтера . Итак, первое, что нужно сделать, это изучить , как реализован этот драйвер. Если вы узнаете, какой компонент выполняет ту работу, которая вам нужна, вы, вероятно, сможете загрузить эту DLL-библиотеку в свой процесс и получить нужный вам результат. Возможно, вы разместили URL, по которому я мог бы скачать этот драйвер?

ОБНОВЛЕНО : Я немного больше о ваших требованиях. Мне кажется, вы можете пойти по пути, предложенному разработчиком драйвера принтера. Если драйвер может печатать на локальный порт FILE, то он может печатать на любом порту принтера. Таким образом, вы можете указать src драйвера сервера мониторинга портов из C: \ WinDDK \ 7600.16385.1 \ src \ print \ monitors \ localmon (см. Также http://msdn.microsoft.com/en-us/library/ff556478%28v=VS.85%29.aspx, http://msdn.microsoft.com/en-us/library/ff549405%28v=VS.85%29.aspx и http://msdn.microsoft.com/en-us/library/ff563806%28v=VS.85%29.aspx). (Я - Windows 32/64 DLL, а не настоящий драйвер), и вносит небольшие изменения. Вместо сохранения результатов в файл, вы можете отправить результаты в ваше приложение. Это будет работать на 100% без каких-либо хитростей. Если вы будете есть некоторые проблемы, чтобы понять localmon Я могу дать вам несколько советов. Это действительно не сложно. Основные изменения, которые вы должны сделать, это изменить LcmStartDocPort LcmWritePort LcmReadPort LcmEndDocPort функций из localmon.c . Некоторая простая вещь, которая отличает Port DLL от обычной DLL, что вместо экспорта всех функций DLL она экспортирует только один InitializePrintMonitor2 с указателями на все другие функции.

ОБНОВЛЕНО 2 : Еще один совет по использованию монитора «Локальный порт». Если идет в конфигурации принтера, затем выберите «Добавить порт ...», выберите «Локальный порт» и нажмите «Новый порт ...», вы можете ввести любое имя файла, например, «C: \ temp \ my.bin». Тогда все, что вы печатаете через принтер, будет напечатано в этом файле без какой-либо пользовательской итерации. Имя может быть любое имя файла win32 (также допускаются имена UNC или именованные каналы). Таким образом, вы можете реализовать некоторые сценарии без программирования с DDK.

ОБНОВЛЕНО 3 : Я посмотрел на драйвер принтера с разных сторон и еще раз посмотрел на API в DDK. Теперь я хочу порекомендовать вам выбрать самый простой способ, и тот, который будет полностью поддерживаться производителем драйвера. Я предлагаю следующее:

Вы устанавливаете принтер с необходимым драйвером и выбираете в качестве выходного порта Локальный порт с фиксированным именем файла (см. Обновление 2). Я назвал здесь имя файла назначения как C: \ TEMP \ Output.afp . Таким образом, вы получите точно такую ​​же ситуацию, как рекомендованный вами драйвер производителя. Фиксированное имя файла абсолютно совпадает с FILE: port. Поэтому, если вы печатаете на принтере, вы получаете файл Output.afp в каталоге C: \ TEMP . Чтобы быть уверенным в конце написания вы можете использовать функции ReadDirectoryChangesW или FindNextChangeNotification / FindFirstChangeNotification с dwNotifyFilter, равным FILE_NOTIFY_CHANGE_LAST_WRITE. Затем вы получите уведомление после последнего времени записи файла. Это означает, что после окончания записи и после FileClose и после того, как кеш достаточно очищен. Таким образом, файл Output.afp не заблокирован, и вы можете действительно безопасно прочитать результаты.

Для печати простых документов вы можете использовать функцию WritePrinter (см. http://msdn.microsoft.com/en-us/library/dd162959%28VS.85%29.aspx и примечание в документации http://msdn.microsoft.com/en-us/library/dd145226%28VS.85%29.aspx). Запись сложных файлов с растровыми изображениями, цветными и различными шрифтами, которые вы должны использовать типичныеGDI API похож на этот в Windows (см. http://msdn.microsoft.com/en-us/library/dd162865%28v=VS.85%29.aspx).

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

7 голосов
/ 30 апреля 2010

(Прошло 10 лет с тех пор, как я делал что-то подобное, но я не думаю, что общие концепции сильно изменились:)

То, что вы хотите сделать, это реализовать собственный процессор печати. Процессор печати - это фрагмент кода, который принимает выходные данные, которые генерирует драйвер принтера, и передает их на устройство вывода. Процессоры печати реализованы как обычные библиотеки пользовательского режима. Вы должны быть в состоянии найти все, что вам нужно, включая примеры, в Windows DDK.

4 голосов
/ 02 мая 2010

Некоторое время назад мы создали коммерческое приложение, которое захватывало потоки печати из любого приложения Windows и преобразовывало результат в изображения формата XML и TIFF.
Мы сделали прототип с DDK, но в итоге купили SDK для захвата печати
SDK был от BlackIce . Несмотря на то, что это был не бесплатный SDK, распределение времени выполнения было бесплатным.

Реализация была сделана с Visual C (неуправляемый) и VB6. Драйвер принтера должен был быть установлен на сервере / ПК, который управлял процессом печати. ​​
Я помню, что сложной задачей было управление настройками принтера во время выполнения (держать сжатые файлы tiffs, каталог вывода для файлов, формат бумаги: A4 или Letter и другие параметры, которые были определены в структуре управления печатью DEVMODE ).

ОБНОВЛЕНИЕ: (Ваш комментарий к @Oleg о MO: DCA P вызвал мою память. Хотя речь идет не о драйвере принтера ...)
Для нашего коммерческого продукта нам также потребовалась настройка для преобразования документов MO: DCA (AFP) в формат tiff и XML.
Этот SDK должен был иметь возможность извлекать как изображения, так и текст ascii, чтобы разрешить последующие преобразования.
Преобразование, которое затем производилось в пакетном режиме из документов AFP в одной папке, в формат XML и tiff.
Мы решили преобразовать файл AFP после его печати (не во время печати).
SDK SnowBound RasterMaster доступен в различных вариантах (мы использовали Windows API с ActiveX, и теперь я вижу, что он доступен для Java ).
Поэтому, если вам необходимо преобразовать документ AFP в какой-то другой формат (извлечь изображения и извлечь текст ascii), вы можете попробовать программное обеспечение из SnowBound. Убедитесь, что у вас также есть опциональная функция , позволяющая извлекать текст ASCII из документов MO DCA.
Этот программный SDK дороже, но он справился со своей работой.
Они предлагают пробную версию здесь .

3 голосов
/ 29 апреля 2010

В данный момент у меня есть одна недостающая ссылка в вашем объяснении, поэтому позвольте мне перефразировать то, что я понял:

  • В вашей системе Windows есть специальный драйвер принтера, который настроен для печати вфайл.
  • Вам нравится иметь простую пакетную программу, которая может что-то дать этому драйверу принтера для вывода двоичного файла.
  • У вас есть набор инструментов, где этот файл может быть дополнительно обработан.

Теперь моя недостающая часть: что вы хотите дать вашему маленькому пакетному сценарию, чтобы он создавал ваш двоичный файл?Есть ли у вас файл Visio, который должен автоматически печататься через этот драйвер?

Если да, вам следует взглянуть на этот маленький пакетный скрипт .Он может взять любой файл с зарегистрированным расширением и отправить его на принтер по умолчанию с настройками по умолчанию.Используя эти настройки , вы можете изменить настройки принтера в вашей системе Windows из пакетного файла, чтобы сделать ваш специальный драйвер драйвером по умолчанию и поместить вывод в файл.

Так что еслиЯ правильно вас понял, у меня не было полного решения, но я думаю, что это хорошая отправная точка для выполнения вашей задачи.

Обновление

Хорошо, прочитав ваш комментарий, я полностью понял, что вам нравитсядостигать.Чтобы это работало, вы должны следовать совету Per Larsens, чтобы написать свой собственный драйвер с Windows ddk (или, точнее, Windows Driver Kit [WDK] ) и инкапсулировать уже существующий драйвер.

Короче говоря, просто: ваш драйвер регистрируется как новый драйвер принтера.Когда он вызывается, он получает все необработанные байты из приложения.Передает его в драйвер, который может сгенерировать ваш файл данных.Получите выходные данные этого драйвера и делайте с ним все, что захотите.

Некоторые примеры для начала можно также найти в MSDN как обзор или, точнее, здесь .

Но просто скажу это заранее: это не легкая или простая задача, и усилия довольно высоки.Возможно, попытка манипулировать настройками драйвера вашего специального драйвера через уже предоставленные пакеты или простое приложение (написанное с помощью AutoIt ) также может решить вашу проблему, просто взаимодействуя (автоматически) с настройками драйвера.

2 голосов
/ 20 мая 2010

Просто повторюсь, возможно, самый простой метод захвата - это использование нового локального порта, настроенного как имя файла. Вы можете отслеживать выходной файл, как описано выше, чтобы поймать вывод.

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

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

Пример LocalMon в Windows Driver Kit является отправной точкой для написания монитора портов. Однако он управляет всеми системными локальными портами и немного сложнее, чем вам нужно. На самом деле, многое из этого просто может сбить вас с толку. Я бы порекомендовал вам начать с LocalMon и сравнить его с исходным кодом Redmon, который намного проще, поскольку управляет выделенным портом. Помните, что исходный код Redmon был взят из localmon очень давно и, похоже, содержит несколько ошибок, поэтому используйте Redmon в качестве ссылки и уменьшите код LocalMon до того, что нужно, чтобы просто записать вывод в файл.

2 голосов
/ 05 мая 2010

Я могу согласиться с тем, что «когда пользователь печатает какой-либо файл на этом конкретном принтере Windows, автоматически захватывает байты, которые были бы отправлены на принтер».

В этом случае вам нужно что-то вроде RedMon , которое перенаправляет байты, которые пошли бы на принтер, на вход для другой программы.

0 голосов
/ 29 апреля 2010

Вы не встраиваете драйверы в исполняемые файлы - драйверы предназначены для взаимодействия операционной системы с оборудованием.

Вы печатаете через операционную систему.

Ваша 'партия' должна выбрать правильный принтер и напечатать ...

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