Impresión desde un servicio .NET

Estoy trabajando en un proyecto en este momento que implica recibir un mensaje de otra aplicación, formatear el contenido de ese mensaje y enviarlo a una impresora. La tecnología de elección es el servicio de Windows C #. El resultado podría llamarse informe, supongo, pero no es necesario un motor de informes. Un motor de plantillas simple, como StringTemplate, o incluso XSLT de salida de HTML estaría bien. El problema que tengo es encontrar una forma gratuita de imprimir este tipo de resultados desde un servicio. Como parece que funcionará, estoy trabajando en un prototipo usando el RDLC de Microsoft, llenando un informe local y luego presentándolo como una imagen a una secuencia de memoria, que luego imprimiré. Los problemas con eso son:

  • La impresión de varias páginas será un gran dolor de cabeza.
  • Todavía tiene que usar PrintDocument para imprimir la secuencia de la memoria, que no está soportada en un Servicio de Windows (aunque puede funcionar, aún no ha llegado tan lejos con el prototipo)
  • Si los datos que se transmiten cambian, tengo que cambiar el conjunto de datos y la clase en la que se deserializan los datos. malo malo malo.

¿Alguien ha tenido que hacer algo remotamente así? ¿Algún consejo? Ya hice una pregunta sobre la impresión de HTML sin la intervención del usuario, y después de perder unos 3 días en eso, he llegado a la conclusión de que no se puede hacer, al menos no con ninguna herramienta disponible de manera gratuita.

Toda la ayuda es apreciada.

EDITAR: Estamos en la versión 2.0 del framework .NET.

Confíe en mí, gastará más dinero tratando de buscar / desarrollar una solución para esto en comparación con la compra de un componente de terceros. No reinvente la rueda y busque la solución paga.

La impresión es un problema complejo y me encantaría ver el día en que se agregue un mejor soporte de framework para esto.

Imprimir desde un servicio de Windows es realmente doloroso. Parece que funciona … a veces … pero finalmente produce o lanza una excepción de vez en cuando, sin ningún motivo claro. Es realmente inútil. Oficialmente, ni siquiera es compatible , sin ninguna explicación ni propuesta para una solución alternativa.

Recientemente, me he enfrentado al problema y después de varias pruebas y experimentos fallidos, finalmente llegué con dos soluciones viables:

  • Escriba su propia DLL de impresión usando la API Win32 (en C / C ++ por ejemplo), luego úsela desde su servicio con P / Invoke (funciona bien)
  • Escriba su propio componente COM + de impresión y luego úselo desde su servicio. He elegido esta solución con éxito recientemente (pero era un componente COM + de terceros, no escrito por mí mismo) Funciona absolutamente bien también.

Lo he hecho. Es un dolor en el A * s. El problema es que la impresión requiere que el motor GDI esté en su lugar, lo que normalmente significa que debe tener el escritorio, que solo se carga cuando está conectado. Si está intentando hacer esto desde un Servicio en un Servidor, entonces normalmente no estás conectado.

Por lo tanto, primero no se puede ejecutar como el usuario del servicio normal, sino como un usuario real que tiene derechos de inicio de sesión interactivos. Luego tienes que ajustar las entradas del registro del servicio (se me olvida cómo, en este momento, tendría que encontrar el código que puedo hacer esta noche si realmente estás interesado). Finalmente, tienes que orar.

Su mayor dolor de cabeza a largo plazo será con los controladores de impresión. Si se está ejecutando como un servicio sin un usuario conectado, a algunos controladores de impresión les gusta abrir cuadros de diálogo de vez en cuando. ¿Qué sucede cuando su impresora se queda sin tóner? ¿O sin papel? El controlador puede mostrar un cuadro de diálogo que nunca se verá y mantener la cola de la impresora porque nadie ha iniciado sesión.

Imprimir desde un servicio es una mala idea. Las impresoras de red están conectadas “por usuario”. Puede marcar el servicio para que se ejecute como un usuario particular, pero consideraría una mala práctica de seguridad. Es posible que pueda conectarse a una impresora local, pero todavía dudaría antes de seguir esta ruta.

La mejor opción es hacer que el servicio almacene los datos y que una aplicación lanzada por el usuario realice la impresión solicitando los datos al servicio. O una ubicación común donde se almacenan los datos, como una base de datos.

Si necesita que los datos se impriman como intervalos regulares, configure un evento de Tarea a través del Progtwigdor de tareas. Lanzar un proceso desde un servicio requerirá conocer el nombre de usuario y la contraseña, lo que nuevamente es una mala práctica de seguridad.

En cuanto a la impresión en sí, utilizar una herramienta de terceros para generar el informe será la más fácil.

Para responder a su primera pregunta, esto puede ser bastante directo dependiendo de los datos. Tenemos una variedad de aplicaciones basadas en servicios que hacen exactamente lo que usted está solicitando. Normalmente, analizamos el archivo entrante y envolvemos nuestro propio Postscript o PCL a su alrededor. Si su diseño es bastante simple, entonces hay algunos códigos PCL muy básicos con los que puede envolver para proporcionar la bandeja de fuente / impresión que desea (con mucho gusto, le daré una orientación aquí fuera de línea).

Si tiene un archivo listo para imprimir, puede enviarlo a una impresora UNC compartida, directamente a una impresora instalada localmente, o incluso a la IP del dispositivo (datos de tipo RAW o LPR).

Sin embargo, si va por la ruta de PDF, el método más simple es enviar la salida de PDF a una impresora que admite la impresión directa de PDF (muchos lo hacen ahora). En este caso, simplemente envíe el PDF al dispositivo y lo imprima.

La otra opción es ejecutar Ghostscript, que debe ser gratuito para sus necesidades (verifique la licencia ya que tienen algunas versiones diferentes, algunos GNU, algunos GPL, etc.) y, o bien usarla en la función de impresión o simplemente convertir a Postscript y enviar a el dispositivo. He usado Ghostscript muchas veces en las aplicaciones de servicio, pero no soy un gran fanático, ya que básicamente estará realizando bombardeos y ejecutando una aplicación de línea de comandos para realizar la conversión. Dicho esto, es una aplicación estable que tiende a fallar con gracia

Puede que esto no sea lo que estás buscando, pero si tuviera que hacerlo de forma rápida y sucia, haría lo siguiente:

  1. Crear una aplicación WPF por separado (para poder usar el manejo integrado de documentos)
  2. Brinde al servicio la capacidad de interactuar con el escritorio (tenga en cuenta que en realidad no tiene que mostrar nada en el escritorio o que haya iniciado sesión para que funcione)
  3. Haga que el servicio ejecute la aplicación y proporciónele los datos para imprimir.

Probablemente también podría manipular esto para imprimir desde un navegador web que ejecute desde el servicio (aunque yo recomendaría construir su propio IE de shell, en lugar de usar un navegador completo).

Para una solución más detallada (también gratuita), la mejor opción es formatear manualmente el documento usted mismo (usando GDI + para hacer el diseño por usted). Esto es tedioso, propenso a errores, lleva mucho tiempo y desperdicia mucho papel durante el desarrollo, pero también le brinda el mayor control sobre lo que le va a la impresora.

Si puede generar una salida para publicar una secuencia de comandos, algunas impresoras imprimirán cualquier cosa que tenga FTP en un directorio determinado.

Usamos esto para superar los créditos impresos que nuestra universidad expuso en nosotros, pero si su servicio tiene salida a un ps entonces usted puede simplemente convertir el archivo ps a la impresora.

Estamos utilizando DevExpress ‘XtraReports para imprimir desde un servicio sin ningún problema. Su modelo de informe es similar al de Windows Forms, por lo que puede insertar dinámicamente elementos de texto y luego emitir el comando de impresión.

Creo que vamos a ir por la ruta de terceros. Me gusta el XSL -> HTML -> PDF -> Flujo de impresora … El HTML de Winnovative a PDF se ve bien para la primera parte, pero me estoy encontrando con un bloque encontrando una buena solución de impresión de PDF … ¿Alguna sugerencia? Lo ideal es que la licencia se base en desarrolladores, no en tiempo de ejecución implementado.

En respuesta a su pregunta sobre la impresión de PDF, no encontré una solución elegante. Estaba ocultando Adobe, que no era confiable y requería que el usuario iniciara sesión en todo momento. Para solucionar este problema específico, solicité que los archivos que procesamos (facturas) se formatearan como archivos Tiff de varias páginas en su lugar, que se pueden dividir e imprimir utilizando las funciones nativas de impresión .NET. La posición de Adobe parece ser “hacer que el usuario vea el archivo en Adobe Reader y puede hacer clic en imprimir”. Inútil.

Todavía estoy ansioso por encontrar una buena forma de producir informes de calidad que se puedan generar desde el servidor web …

La impresión mediante System.Drawing.Printing no es compatible con MS, según la respuesta de Yann Trevin. Sin embargo, es posible que pueda usar la nueva Impresión del sistema basada en WPF ( creo )