2008-08-11 22 views
19

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. Dado que parece que funcionará, estoy trabajando en un prototipo usando el RDLC de Microsoft, rellenando un informe local y luego presentándolo como una imagen a una secuencia de memoria, que luego imprimiré. Los problemas con eso son:Impresión desde un servicio .NET

  • La impresión de varias páginas será un gran dolor de cabeza.
  • todavía tiene que utilizar PrintDocument para imprimir la secuencia de memoria, que no se sostiene en un servicio de Windows (aunque puede trabajar - no han llegado tan lejos con el prototipo aún)
  • Si los datos que llegan a través de los cambios, no tengo para 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 ayuda es apreciada.

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

Respuesta

13

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 un tercero. 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 una mejor compatibilidad de marcos para esto.

1

esto puede no ser lo que usted está buscando, pero si que tenía que hacer esto rápido &, lo haría sucia:

  1. Crear una aplicación de WPF separada (por lo que podría utilizar el documento incorporado manejo)
  2. Otorgue al servicio la capacidad de interactuar con el escritorio (tenga en cuenta que en realidad no tiene que mostrar nada en el escritorio, o inicie sesión para que funcione)
  3. Haga que el servicio ejecute la aplicación, y dale los datos para imprimir.

Probablemente también pueda insertar esto para imprimir desde un navegador web que ejecute desde el servicio (aunque yo recomendaría construir su propio IE 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.

8

La impresión desde un servicio de Windows es realmente dolorosa. 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, es incluso not supported, sin ninguna explicación, ni ninguna propuesta para una solución alternativa.

Recientemente, he tenido que hacer frente al problema y después de varios intentos fallidos y experimentaciones, llegué finalmente con dos soluciones viables:

  • Escriba su propia DLL de impresión que utiliza la API de Win32 (en C/C++ para ejemplo), luego úselo 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.
+2

GDI + nunca fue diseñado/probado para funcionar en contexto de servicio. Por eso no funciona. Deberías usar GDI y funcionar para dibujar. Consulte este documento para encontrar llamadas Win32 equivalentes: http://msdn.microsoft.com/en-us/library/aa302340.aspx#win32map_printingfunctions – Signcodeindie

0

Creo que vamos a ir por la ruta de terceros. Me gusta el XSL -> HTML -> PDF -> Flujo de impresora ... El HTML to PDF de Winnovative se ve bien para la primera parte, pero me estoy encontrando con un bloque para encontrar 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.

4

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 imprimir los datos como intervalos regulares, configure un evento de Tarea a través del Programador 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.

3

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).

Si, sin embargo, 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 debería ser gratuito para sus necesidades (verifique la licencia ya que tienen algunas versiones diferentes, algunas GNU, algunas GPL, etc.) y utilícelas en función de impresión o simplemente conviértanse en Postscript y enviar al 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

5

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 usted normalmente no está conectado.

Así que 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.

1

Si puede generar una salida para publicar la secuencia de comandos, algunas impresoras imprimirán todo lo que se transfiere a un determinado directorio en ellas.

Utilizamos 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.

0

En respuesta a su pregunta sobre la impresión de PDF, no he encontrado 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 interesado en encontrar una buena manera de producir informes de calidad que pueden ser de salida desde el servidor web ...

0

de impresión que usa System.Drawing.Printing no es compatible con MS, de acuerdo con la respuesta de Yann Trevin . Sin embargo, es posible que pueda utilizar la nueva, basada en WPF, System.Printing (I que)

1

Estamos utilizando DevExpress' XtraReports 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.

Cuestiones relacionadas