Печать из службы.NET

Сейчас я работаю над проектом, который включает получение сообщения из другого приложения, форматирование содержимого этого сообщения и отправку его на принтер. Выбранная технология - C# windows service. Вывод можно назвать отчетом, я полагаю, но механизм отчетов не требуется. Подойдет простой шаблонизатор, такой как StringTemplate или даже XSLT, выводящий HTML. Проблема, с которой я столкнулся, заключается в том, чтобы найти бесплатный способ распечатать этот вид вывода из службы. Поскольку кажется, что это будет работать, я работаю над прототипом с использованием Microsoft RDLC, заполняю локальный отчет и затем отображаю его в виде изображения в потоке памяти, который я затем распечатаю. Проблемы с этим:

  • Многостраничная печать будет большой головной болью.
  • Тем не менее, необходимо использовать PrintDocument для печати потока памяти, который не поддерживается в службе Windows (хотя это может работать - еще не дошли до прототипа)
  • Если встречающиеся данные изменяются, я должен изменить набор данных и класс, в который данные десериализуются. плохо плохо плохо

Кто-нибудь должен был сделать что-нибудь подобное удаленно? Любой совет? Я уже опубликовал вопрос о печати HTML без участия пользователя, и, потратив на это около 3 дней, я пришел к выводу, что этого нельзя сделать, по крайней мере, с помощью любого свободно доступного инструмента.

Вся помощь приветствуется.

РЕДАКТИРОВАТЬ: Мы находимся на версии 2.0.NET Framework.

11 ответов

Решение

Поверьте мне, вы потратите больше денег, пытаясь найти / разработать решение для этого, по сравнению с покупкой стороннего компонента. Не изобретайте велосипед и отправляйтесь за платным решением.

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

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

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

  • Напишите свою собственную библиотеку печати с помощью Win32 API (например, на C/C++), а затем используйте ее из своего сервиса с P/Invoke (работает нормально)
  • Написать свой собственный компонент печати COM+, а затем использует его из вашего сервиса. Недавно я с успехом выбрал это решение (но это был сторонний компонент COM+, а не собственноручно написанное). Оно тоже работает абсолютно нормально.

Я сделал это. Это боль в A*s. Проблема заключается в том, что для печати требуется наличие механизма GDI, что обычно означает, что у вас должен быть рабочий стол, который загружается только при входе в систему. Если вы пытаетесь сделать это из службы на сервере, тогда вы обычно не залогинены.

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

Ваша самая большая долгосрочная головная боль будет с драйверами печати. Если вы работаете в качестве службы без вошедшего в систему пользователя, некоторые драйверы печати время от времени любят всплывать диалоговые окна. Что происходит, когда в вашем принтере заканчивается тонер? Или из бумаги? Драйвер может вызвать диалоговое окно, которое никогда не будет видно, и задержать очередь принтера, потому что никто не вошел в систему!

Чтобы ответить на ваш первый вопрос, это может быть довольно простым в зависимости от данных. У нас есть множество сервисных приложений, которые выполняют именно то, что вы просите. Как правило, мы анализируем входящий файл и оборачиваем его собственным Postscript или PCL. Если ваш макет довольно прост, то есть несколько очень простых кодов PCL, которые вы можете обернуть в него, чтобы обеспечить желаемый макет шрифта / печати (я был бы более чем рад дать вам некоторое руководство здесь в автономном режиме).

Если у вас есть готовый к печати файл, вы можете отправить его на общий принтер UNC, непосредственно на локально установленный принтер или даже на IP-адрес устройства (данные типа RAW или LPR).

Однако, если вы идете по пути PDF, самый простой способ - отправить вывод PDF на принтер, который поддерживает прямую печать PDF (многие это делают сейчас). В этом случае вы просто отправляете PDF на устройство и распечатываете его.

Другой вариант - запустить Ghostscript, который должен быть бесплатным для ваших нужд (проверьте лицензирование, поскольку у них есть несколько разных версий, немного GNU, немного GPL и т. Д.) И либо используйте встроенную функцию печати, либо просто преобразуйте в Postscript и отправьте в Устройство. Я много раз использовал Ghostscript в приложениях-службах, но не большой поклонник, так как вы будете в основном выполнять оболочку и запускать приложение командной строки для выполнения преобразования. Тем не менее, это стабильное приложение, которое имеет тенденцию терпеть неудачу изящно

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

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

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

Что касается самой печати, использовать сторонний инструмент для генерации отчета будет проще всего.

Если вы можете вывести на пост-скрипт, некоторые принтеры будут печатать все, что будет FTP передано в определенный каталог на них.

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

Мы используем DevExpress XtraReports для печати из сервиса без каких-либо проблем. Их модель отчета аналогична модели Windows Forms, поэтому вы можете динамически вставлять текстовые элементы и затем вводить команду печати.

Это может быть не то, что вы ищете, но если бы мне нужно было сделать это быстро и грязно, я бы:

  1. Создайте отдельное приложение WPF (чтобы я мог использовать встроенную обработку документов)
  2. Дайте службе возможность взаимодействовать с рабочим столом (обратите внимание, что на самом деле вам не нужно ничего показывать на рабочем столе или войти в систему, чтобы это работало)
  3. Пусть служба запустит приложение и предоставит данные для печати.

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

Для более подробного (также бесплатного) решения лучше всего вручную отформатировать документ вручную (используя GDI+, чтобы сделать макет для вас). Это утомительно, подвержено ошибкам, отнимает много времени и тратит много бумаги во время разработки, но также дает вам максимальный контроль над тем, что происходит с принтером.

Я думаю, что мы собираемся пойти сторонним маршрутом. Мне нравится XSL -> HTML -> PDF -> Поток принтера... HTML в PDF от Winnovative выглядит хорошо для первой части, но я наталкиваюсь на блок, находящий хорошее решение для печати PDF... какие-нибудь предложения? В идеале лицензия должна быть для разработчика, а не для развернутой среды выполнения.

Отвечая на ваш вопрос о печати PDF, я не нашел элегантного решения. Я был "оболочкой" для Adobe, который был ненадежным и требовал, чтобы пользователь всегда входил в систему. Чтобы решить эту конкретную проблему, я попросил отформатировать обрабатываемые нами файлы (счета-фактуры) в виде многостраничных файлов Tiff, которые можно разделить и распечатать с помощью встроенных функций печати.NET. Похоже, что позиция Adobe заключается в том, чтобы "заставить пользователей просмотреть файл в Adobe Reader, и они смогут нажать" Печать ". Бесполезный.

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

Согласно ответу Янна Тревина, печать с использованием System.Drawing.Printing не поддерживается MS. Тем не менее, вы можете использовать новую, основанную на WPF, System.Printing (я думаю)

Другие вопросы по тегам