¿Cómo puedo enviar un documento de archivo a la impresora y hacer que se imprima?
Aquí está la premisa básica:
Mi usuario hace clic en algunos artilugios y se escupe un archivo PDF en su escritorio. ¿Hay alguna manera de enviar este archivo a la cola de la impresora y hacer que se imprima en la impresora conectada localmente?
string filePath = "filepathisalreadysethere";
SendToPrinter(filePath); //Something like this?
Hará este proceso muchas veces. Para cada estudiante en un salón de clase tiene que imprimir una pequeña boleta de calificaciones. Así que genero un PDF para cada estudiante y me gustaría automatizar el proceso de impresión en lugar de que el usuario genere un PDF, imprima, genere un PDF, imprima, genere un PDF, imprima.
¿Alguna sugerencia sobre cómo abordar esto? Estoy ejecutando Windows XP con Windows Forms .NET 4.
Encontré esta pregunta de StackOverflow donde la respuesta aceptada sugiere:
Una vez que haya creado sus archivos, puede imprimirlos a través de una línea de comando (puede usar la clase Command que se encuentra en el espacio de nombres System.Diagnostics para eso)
¿Cómo lograría esto?
Agregar una nueva respuesta a esto ya que la cuestión de imprimir archivos PDF en .net existe desde hace mucho tiempo y la mayoría de las respuestas son anteriores a la biblioteca Google Pdfium, que ahora tiene un contenedor .net. En mi caso, estaba investigando este problema por mi cuenta y seguía quedando en blanco, intentando crear soluciones hackers como generar Acrobat u otros lectores de PDF, o encontrarme con bibliotecas comerciales que son costosas y no tienen términos de licencia muy compatibles. Pero la biblioteca Google Pdfium y el contenedor PdfiumViewer .net son de código abierto, por lo que son una gran solución para muchos desarrolladores, incluido yo mismo. PdfiumViewer tiene la licencia Apache 2.0.
Puede obtener el paquete NuGet aquí:
https://www.nuget.org/packages/PdfiumViewer/
y puedes encontrar el código fuente aquí:
https://github.com/pvginkel/PdfiumViewer
Aquí hay un código simple que imprimirá silenciosamente cualquier cantidad de copias de un archivo PDF a partir de su nombre de archivo. También puedes cargar archivos PDF desde una secuencia (que es como lo hacemos normalmente), y puedes descubrirlo fácilmente mirando el código o los ejemplos. También hay una vista de archivos PDF de WinForm para que también pueda renderizar los archivos PDF en una vista o realizar una vista previa de impresión en ellos. Para nosotros, simplemente necesitaba una forma de imprimir silenciosamente el archivo PDF en una impresora específica a pedido.
public bool PrintPDF(
string printer,
string paperName,
string filename,
int copies)
{
try {
// Create the printer settings for our printer
var printerSettings = new PrinterSettings {
PrinterName = printer,
Copies = (short)copies,
};
// Create our page settings for the paper size selected
var pageSettings = new PageSettings(printerSettings) {
Margins = new Margins(0, 0, 0, 0),
};
foreach (PaperSize paperSize in printerSettings.PaperSizes) {
if (paperSize.PaperName == paperName) {
pageSettings.PaperSize = paperSize;
break;
}
}
// Now print the PDF document
using (var document = PdfDocument.Load(filename)) {
using (var printDocument = document.CreatePrintDocument()) {
printDocument.PrinterSettings = printerSettings;
printDocument.DefaultPageSettings = pageSettings;
printDocument.PrintController = new StandardPrintController();
printDocument.Print();
}
}
return true;
} catch {
return false;
}
}
Puede decirle a Acrobat Reader que imprima el archivo usando (como alguien ya mencionó aquí) el verbo 'imprimir'. Después de eso, también necesitarás cerrar Acrobat Reader mediante programación:
private void SendToPrinter()
{
ProcessStartInfo info = new ProcessStartInfo();
info.Verb = "print";
info.FileName = @"c:\output.pdf";
info.CreateNoWindow = true;
info.WindowStyle = ProcessWindowStyle.Hidden;
Process p = new Process();
p.StartInfo = info;
p.Start();
p.WaitForInputIdle();
System.Threading.Thread.Sleep(3000);
if (false == p.CloseMainWindow())
p.Kill();
}
Esto abre Acrobat Reader y le indica que envíe el PDF a la impresora predeterminada y luego cierra Acrobat después de tres segundos.
Si está dispuesto a enviar otros productos con su aplicación, puede utilizar GhostScript (gratis) o una impresora PDF de línea de comandos como http://www.commandlinepdf.com/ (comercial).
Nota: el código de muestra abre el PDF en la aplicación actualmente registrada para imprimir archivos PDF , que es Adobe Acrobat Reader en la mayoría de las máquinas. Sin embargo, es posible que utilicen un visor de PDF diferente, como Foxit ( http://www.foxitsoftware.com/pdf/reader/ ). Sin embargo, el código de muestra aún debería funcionar.
Sé que la etiqueta dice Windows Forms
... pero, si alguien está interesado en algún WPF
método de aplicación, System.Printing
funciona de maravilla.
var file = File.ReadAllBytes(pdfFilePath);
var printQueue = LocalPrintServer.GetDefaultPrintQueue();
using (var job = printQueue.AddJob())
using (var stream = job.JobStream)
{
stream.Write(file, 0, file.Length);
}
Sólo recuerde incluir System.Printing
la referencia, si aún no está incluida. Ahora bien, este método no funciona bien con ASP.NET
o Windows Service
. No debe usarse con Windows Forms
, como lo ha hecho System.Drawing.Printing
. No tengo ningún problema con la impresión de mi PDF usando el código anterior.
Sin embargo, debo mencionar que si su impresora no admite la impresión directa para el formato de archivo PDF, no tendrá suerte con este método.
El siguiente fragmento de código es una adaptación del código de Kendall Bennett para imprimir archivos pdf usando la PdfiumViewer
biblioteca. La principal diferencia es que se utiliza una secuencia en lugar de un archivo.
public bool PrintPDF(
string printer,
string paperName,
int copies, Stream stream)
{
try
{
// Create the printer settings for our printer
var printerSettings = new PrinterSettings
{
PrinterName = printer,
Copies = (short)copies,
};
// Create our page settings for the paper size selected
var pageSettings = new PageSettings(printerSettings)
{
Margins = new Margins(0, 0, 0, 0),
};
foreach (PaperSize paperSize in printerSettings.PaperSizes)
{
if (paperSize.PaperName == paperName)
{
pageSettings.PaperSize = paperSize;
break;
}
}
// Now print the PDF document
using (var document = PdfiumViewer.PdfDocument.Load(stream))
{
using (var printDocument = document.CreatePrintDocument())
{
printDocument.PrinterSettings = printerSettings;
printDocument.DefaultPageSettings = pageSettings;
printDocument.PrintController = new StandardPrintController();
printDocument.Print();
}
}
return true;
}
catch (System.Exception e)
{
return false;
}
}
En mi caso, estoy generando el archivo PDF usando una biblioteca llamada PdfSharp
y luego guardando el documento en una secuencia de esta manera:
PdfDocument pdf = PdfGenerator.GeneratePdf(printRequest.html, PageSize.A4);
pdf.AddPage();
MemoryStream stream = new MemoryStream();
pdf.Save(stream);
MemoryStream stream2 = new MemoryStream(stream.ToArray());
Una cosa que quiero señalar y que podría ser útil para otros desarrolladores es que tuve que instalar la versión de 32 bits de la DLL nativa de Pdfium para que la impresión funcionara aunque esté ejecutando Windows 10 de 64 bits. Instalé los siguientes dos paquetes NuGet usando el administrador de paquetes NuGet en Visual Studio:
PdfiumViewer
PdfiumViewer.Native.x86.v8-xfa