Pergunta

Estou trabalhando em um projeto que envolve receber uma mensagem de outro aplicativo, formatar o conteúdo dessa mensagem e enviá-la para uma impressora.A tecnologia escolhida é o serviço Windows C#.A saída poderia ser chamada de relatório, suponho, mas um mecanismo de relatório não é necessário.Um mecanismo de modelagem simples, como StringTemplate, ou mesmo XSLT com saída HTML seria adequado.O problema que estou tendo é encontrar uma maneira gratuita de imprimir esse tipo de saída de um serviço.Desde que parece para que funcione, estou trabalhando em um protótipo usando o RDLC da Microsoft, preenchendo um relatório local e depois renderizando-o como uma imagem em um fluxo de memória, que irei imprimir.Os problemas com isso são:

  • A impressão de várias páginas será uma grande dor de cabeça.
  • Ainda tenho que usar PrintDocument para imprimir o fluxo de memória, que não é suportado em um serviço do Windows (embora possa funcionar - ainda não cheguei tão longe com o protótipo)
  • Se os dados recebidos mudarem, terei que alterar o conjunto de dados e a classe na qual os dados estão sendo desserializados.mau Mau Mau.

Alguém já teve que fazer algo remotamente assim?Algum conselho?Já postei uma pergunta sobre a impressão de HTML sem a intervenção do usuário e, depois de perder cerca de 3 dias com isso, cheguei à conclusão de que isso não pode ser feito, pelo menos não com nenhuma ferramenta disponível gratuitamente.

Toda ajuda é apreciada.

EDITAR:Estamos na versão 2.0 do .NET framework.

Foi útil?

Solução

Acredite em mim, você gastará mais dinheiro tentando pesquisar/desenvolver uma solução para isso do que comprar um componente de terceiros.Não reinvente a roda e opte pela solução paga.

A impressão é um problema complexo e eu adoraria ver o dia em que um melhor suporte de estrutura fosse adicionado para isso.

Outras dicas

Imprimir a partir de um serviço do Windows é muito doloroso.Parece funcionar...às vezes...mas finalmente trava ou lança uma exceção de vez em quando, sem qualquer motivo claro.É realmente impossível.Oficialmente, é mesmo não suportado, sem qualquer explicação, nem qualquer proposta de solução alternativa.

Recentemente, fui confrontado com o problema e depois de vários testes e experimentações malsucedidas, finalmente encontrei duas soluções viáveis:

  • Escreva sua própria DLL de impressão usando a API Win32 (em C/C++, por exemplo) e use-a em seu serviço com P/Invoke (funciona bem)
  • Escreva seu próprio componente COM+ de impressão e use-o em seu serviço.Eu escolhi esta solução com sucesso recentemente (mas era um componente COM+ de terceiros, não escrito por mim). Ela também funciona perfeitamente bem.

Eu fiz isso.É uma dor de cabeça.O problema é que a impressão exige que o mecanismo GDI esteja instalado, o que normalmente significa que você precisa da área de trabalho, que só carrega quando você está logado.Se você estiver tentando fazer isso a partir de um serviço em um servidor, normalmente não estará conectado.

Então, primeiro você não pode executar como um usuário de serviço normal, mas como um usuário real que possui direitos de login interativos.Então você tem que ajustar as entradas do registro do serviço (esqueci como no momento, teria que encontrar o código que posso fazer hoje à noite se você estiver realmente interessado).Finalmente, você tem que orar.

Sua maior dor de cabeça a longo prazo será com os drivers de impressão.Se você estiver executando como um serviço sem um usuário conectado, alguns drivers de impressão gostam de exibir caixas de diálogo de vez em quando.O que acontece quando a impressora fica sem toner?Ou sem papel?O driver pode exibir uma caixa de diálogo que nunca será vista e atrasar a fila da impressora porque ninguém está logado!

Imprimir a partir de um serviço é uma má ideia.As impressoras de rede são conectadas “por usuário”.Você pode marcar o serviço para ser executado como um usuário específico, mas consideraria isso uma prática de segurança inadequada.Você pode conseguir se conectar a uma impressora local, mas ainda hesitaria antes de seguir esse caminho.

A melhor opção é fazer com que o serviço armazene os dados e que um aplicativo iniciado pelo usuário faça a impressão solicitando os dados ao serviço.Ou um local comum onde os dados são armazenados, como um banco de dados.

Se você precisar imprimir os dados em intervalos regulares, configure um evento de tarefa por meio do Agendador de tarefas.O lançamento de um processo a partir de um serviço exigirá o conhecimento do nome de usuário e da senha, o que novamente é uma prática de segurança ruim.

Quanto à impressão em si, utilizar uma ferramenta de terceiros para gerar o relatório será o mais fácil.

Para responder à sua primeira pergunta, isso pode ser bastante simples, dependendo dos dados.Temos uma variedade de aplicativos baseados em serviços que fazem exatamente o que você está pedindo.Normalmente, analisamos o arquivo recebido e agrupamos nosso próprio Postscript ou PCL em torno dele.Se o layout for bastante simples, existem alguns códigos PCL muito básicos com os quais você pode envolvê-los para fornecer o layout de fonte/impressão desejado (ficaria feliz em fornecer algumas orientações aqui off-line).

Se você tiver um arquivo pronto para impressão, poderá enviá-lo para uma impressora UNC compartilhada, diretamente para uma impressora instalada localmente ou até mesmo para o IP do dispositivo (dados do tipo RAW ou LPR).

Se, no entanto, você estiver seguindo o caminho do PDF, o método mais simples é enviar a saída do PDF para uma impressora que suporte impressão direta de PDF (muitas agora o fazem).Neste caso basta enviar o PDF para o aparelho e ele imprime.

A outra opção é lançar Ghostscript que deve ser gratuito para suas necessidades (verifique o licenciamento, pois eles têm algumas versões diferentes, algumas GNU, algumas GPL etc.) e use a função de impressão integrada ou simplesmente converta para Postscript e envie para o dispositivo.Eu usei o Ghostscript muitas vezes em aplicativos de serviço, mas não sou um grande fã, pois você basicamente gastará e executará um aplicativo de linha de comando para fazer a conversão.Dito isto, é um aplicativo estável que tende a falhar normalmente

Pode não ser isso que você está procurando, mas se eu precisasse fazer isso rápido e sujo, eu faria:

  1. Crie um aplicativo WPF separado (para que eu possa usar o gerenciamento de documentos integrado)
  2. Dê ao serviço a capacidade de interagir com a área de trabalho (observe que você não precisa mostrar nada na área de trabalho ou estar logado para que isso funcione)
  3. Faça com que o serviço execute o aplicativo e forneça os dados para impressão.

Você provavelmente também poderia fazer isso para imprimir a partir de um navegador da Web executado a partir do serviço (embora eu recomende construir seu próprio shell IE, em vez de usar um navegador completo).

Para uma solução mais detalhada (também gratuita), sua melhor aposta é provavelmente formatar manualmente o documento (usando GDI+ para fazer o layout para você).Isso é tedioso, sujeito a erros, demorado e desperdiça muito papel durante o desenvolvimento, mas também oferece maior controle sobre o que vai para a impressora.

Se você puder enviar para post script, algumas impressoras imprimirão qualquer coisa que seja enviada por FTP para um determinado diretório.

Usamos isso para superar os créditos de impressão que nossa universidade nos expôs, mas se o seu serviço resultar em um ps, você pode simplesmente enviar por FTP o arquivo ps para a impressora.

Nós estamos usando XtraReports do DevExpress imprimir de um serviço sem problemas.Seu modelo de relatório é semelhante ao do Windows Forms, portanto você pode inserir elementos de texto dinamicamente e depois emitir o comando de impressão.

Acho que vamos seguir o caminho de terceiros.Gosto de XSL -> HTML -> PDF -> Fluxo da impressora...Winnovative's HTML para PDF parece bom para a primeira parte, mas estou enfrentando dificuldades para encontrar uma boa solução de impressão de PDF ...alguma sugestão?Idealmente, a licença seria baseada no desenvolvedor e não no tempo de execução implantado.

Em resposta à sua pergunta sobre a impressão de PDF, não encontrei uma solução elegante.Eu estava "desembolsando" para a Adobe, que não era confiável e exigia que um usuário estivesse logado o tempo todo.Para corrigir esse problema específico, solicitei que os arquivos que processamos (faturas) fossem formatados como arquivos Tiff de várias páginas, que podem ser divididos e impressos usando funções de impressão nativas do .NET.A posição da Adobe parece ser "fazer com que o usuário visualize o arquivo no Adobe Reader e clique em imprimir".Inútil.

Ainda estou interessado em encontrar uma boa maneira de produzir relatórios de qualidade que possam ser produzidos no servidor web...

Imprimir usando System.Drawing.Printing não é suportado pela MS, conforme resposta de Yann Trevin.No entanto, você pode usar o novo System.Printing (I pensar)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top