Pregunta

Se me ha exigido que una aplicación web interna envíe documentos a una impresora de forma transparente. La idea sería que el usuario pueda seleccionar su impresora más cercana, y la aplicación web enviaría sus trabajos de impresión a la impresora que seleccionó.

La primera impresora con la que tenemos que implementar son los cánones, por lo que mi pregunta es: ¿cómo haría para enviar un documento para imprimir en la red a un Canon específico? El tipo de Cannon es cuestión es un iR5570 y los documentos que se dirán serán principalmente Word y PDF

Actualmente estoy abriéndome camino a través del terrible sitio para desarrolladores de Canon, solo IE, pero espero que alguien pueda orientarme en la dirección correcta o dirigirme a una asamblea de terceros :)

¿Fue útil?

Solución

La frase clave en esa pregunta es 'aplicación web'.

En una aplicación web normal que usa solo HTML + Javascript sobre HTTP, no puede simplemente enviar un documento directamente a una impresora. Esa es una de las razones por las que existen los navegadores web, y sin esa funcionalidad, todas las impresoras recopilarían el mismo tipo de basura que una máquina de fax pública.

Entonces necesitas algún tipo de solución. Una opción es construir sobre un complemento común, como flash, silverlight, java applet o incluso algo como greasemonkey. Otro es un complemento personalizado, como un control de winforms alojado o una extensión de navegador personalizada.

Eres muy afortunado, ya que parece que tienes un control completo (o conocimiento) del entorno de implementación, y que este entorno es bastante homogéneo. Esto significa que tiene una opción adicional que otros han comenzado a explorar. Si puede instalar todas las impresoras en su entorno en el servidor web, entonces es bastante fácil usar las clases de impresoras .Net integradas (en el espacio de nombres System.Drawing.Printing ) para enumerarlas impresora, muéstreselos al usuario para que puedan elegir o mantener algún tipo de IP en la tabla de mapeo de impresoras, y luego imprima directamente a esa impresora desde su aplicación web. Tenga en cuenta que este esquema puede requerir que su aplicación se ejecute a un nivel de confianza superior al que se requeriría de otro modo.

Ahora se trata de imprimir realmente sus documentos PDF y Word. Para acrobat, consulte este enlace:
http: //support.adobe.com/devsup/devsup.nsf/docs/52080.htm (máquina Wayback)
Tenga en cuenta que está un poco anticuado, pero creo que el concepto sigue siendo válido. Tendrá que experimentar un poco para asegurarse de que funcione como se esperaba.

Para Word, normalmente no soy fanático de la interoperabilidad / automatización de Office en una aplicación web. Pero en este caso no está editando ningún documento: solo lo carga el tiempo suficiente para imprimir. Y el hecho de que dependa de otro recurso escaso (las impresoras) debería evitar que esto se amplíe más allá de lo que su servidor web podría hacer frente. Por lo tanto, puede tener un caso raro en el que la automatización de Office en un proyecto web tiene sentido.

Otros consejos

Muchas impresoras y dispositivos multifunción actuales admiten la impresión de archivos PDF directamente, esto puede resolver uno de sus problemas. Simplemente envíe el PDF a la impresora. De hecho, algunos incluso admiten el envío de una URL y la impresora irá a buscar el documento e imprimirlo. Lexmark seguro lo hace y creo que algunos otros proveedores también lo hacen. Esto todavía significa que debe lidiar con el documento de Word. Word 2007 admite PDF (con add- instalado desde Microsoft ) y he usado esta función programáticamente con gran éxito en C #.

Aquí está el código para eso:

Microsoft.Office.Interop.Word.ApplicationClass msWord = new Microsoft.Office.Interop.Word.ApplicationClass();

object paramUnknown = Type.Missing;
object missing = Type.Missing;
object paramSaveChangesNo = Microsoft.Office.Interop.Word.WdSaveOptions.wdDoNotSaveChanges;
//object paramFonts = Microsoft.Office.Interop.Word.wde
object paramFormatPDF = Microsoft.Office.Interop.Word.WdSaveFormat.wdFormatPDF;
object paramTrue = true;
object paramReadOnly = true;  
object sourceDoc = @"c:\input.doc"                              
object target = @"c:\output.pdf";

msWord.Visible = false;

//open .doc
msWord.Documents.Open(ref sourceDoc, ref paramUnknown, ref paramReadOnly, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown);

//so it won't show on the taskbar
msWord.Application.Visible = false;
msWord.WindowState = Microsoft.Office.Interop.Word.WdWindowState.wdWindowStateMinimize;

//save .doc to new target name and format
msWord.ActiveDocument.SaveAs(ref targetDoc, ref paramFormatPDF, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramTrue, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown, ref paramUnknown);

msWord.ActiveDocument.Close(ref missing, ref missing, ref missing);

msWord.Quit(ref paramSaveChangesNo, ref paramUnknown, ref paramUnknown);

Por último, si su dispositivo no admite la impresión de PDF, puede usar Ghostscript u otras herramientas para convertir su PDF a PS o incluso PCL. No es lo mejor, ya que significa ejecutar un pequeño código no administrado o el peor de los casos, descartar y ejecutar la línea de comando GS, dicho esto, actualmente lo hacemos en una de nuestras aplicaciones web y funciona bien. Por otro lado, no lo hacemos para imprimir, sino para unir varios archivos PDF juntos, pero al final funcionará igual.

El PrintDocument la documentación contiene un ejemplo detallado de impresión desde C # . El nombre de la impresora debe apuntar a una impresora local o un recurso compartido de impresora. Consulte printing-to-a-pdf-printer-programáticamente para imprimir documentos PDF .

Algo tiene que traducir sus documentos de Word y PDF en algo que la impresora entienda. Normalmente, esto sería Word en sí para el primero, y algún tipo de visor de PDF para el segundo. Esos programas deben recibir instrucciones sobre a qué impresora enviar la salida.

Una forma posible de hacerlo sería guardar los documentos como archivos Postscript. Luego, podrían enviarse a una impresora compatible con Postscript directamente desde una aplicación C #. Esa sería probablemente la forma más fácil de hacerlo.

Puede valer 5 minutos verificar las capacidades del servicio de informes SQL. Lo he usado en el pasado para renderizar pdf directamente para imprimir.

http://blogs.msdn.com/bryanke/articles/71491.aspx

Si Windows conoce los tipos de documentos en cuestión (como deberían ser DOC y PDF), ¿puede usar los verbos de Windows para hacerlo?

Ejemplo de Codeproject PDF: Conversión de PDF automatizada utilizando el software gratuito PDF995 y FreePDF_XP Impresoras MSDN: verbos y asociaciones de archivos

Este código funciona perfectamente Utiliza Adobe Reader para imprimir

Consejos para usar 1- no olvides proporcionar tu propia ruta de instalación a adobe reader 2- Obtenga el nombre de la impresora de Propiedades de la impresora con la que desea imprimir

usa la clase así:

PdfFilePrinter p = new PdfFilePrinter();

p.PdfFileName = @"c:\1.pdf";
p.Print();
p.PdfFileName = @"c:\2.pdf";
p.Print();

y la clase es:

public class PdfFilePrinter
{
    /// <summary>
    /// Initializes a new instance of the <see cref="PdfFilePrinter"/> class.
    /// </summary>
    public PdfFilePrinter()
    {
        adobeReaderPath = @"C:\Program Files\Adobe\Reader 9.0\Reader\AcroRd32.exe";
        printerName = "HP LaserJet P2055 Series PCL6";
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="PdfFilePrinter"/> class.
    /// </summary>
    /// <param name="pdfFileName">Name of the PDF file.</param>
    public PdfFilePrinter(string pdfFileName)
    {
        this.PdfFileName = pdfFileName;
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="PdfFilePrinter"/> class.
    /// </summary>
    /// <param name="pdfFileName">Name of the PDF file.</param>
    /// <param name="printerName">Name of the printer.</param>
    public PdfFilePrinter(string pdfFileName, string printerName)
    {
        this.pdfFileName = pdfFileName;
        this.printerName = printerName;
    }

    /// <summary>
    /// Gets or sets the name of the PDF file to print.
    /// </summary>
    public string PdfFileName
    {
        get { return this.pdfFileName; }
        set { this.pdfFileName = value; }
    }
    string pdfFileName;

    /// <summary>
    /// Gets or sets the name of the printer. A typical name looks like '\\myserver\HP LaserJet PCL5'.
    /// </summary>
    /// <value>The name of the printer.</value>
    public string PrinterName
    {
        get { return this.printerName; }
        set { this.printerName = value; }
    }
    string printerName;

    /// <summary>
    /// Gets or sets the working directory.
    /// </summary>
    public string WorkingDirectory
    {
        get { return this.workingDirectory; }
        set { this.workingDirectory = value; }
    }
    string workingDirectory;

    /// <summary>
    /// Prints the PDF file.
    /// </summary>
    public void Print()
    {
        Print(-1);
    }

    /// <summary>
    /// Prints the PDF file.
    /// </summary>
    /// <param name="milliseconds">The number of milliseconds to wait for completing the print job.</param>
    public void Print(int milliseconds)
    {
        if (this.printerName == null || this.printerName.Length == 0)
            this.printerName = PdfFilePrinter.defaultPrinterName;

        if (PdfFilePrinter.adobeReaderPath == null || PdfFilePrinter.adobeReaderPath.Length == 0)
            throw new InvalidOperationException("No full qualified path to AcroRd32.exe or Acrobat.exe is set.");

        if (this.printerName == null || this.printerName.Length == 0)
            throw new InvalidOperationException("No printer name set.");

        // Check whether file exists.
        string fqName = String.Empty;
        if (this.workingDirectory != null && this.workingDirectory.Length != 0)
            fqName = Path.Combine(this.workingDirectory, this.pdfFileName);
        else
            fqName = Path.Combine(Directory.GetCurrentDirectory(), this.pdfFileName);
        if (!File.Exists(fqName))
            throw new InvalidOperationException(String.Format("The file {0} does not exist.", fqName));

        // TODO: Check whether printer exists.

        try
        {
            DoSomeVeryDirtyHacksToMakeItWork();

            //acrord32.exe /t          <- seems to work best
            //acrord32.exe /h /p       <- some swear by this version
            ProcessStartInfo startInfo = new ProcessStartInfo();
            startInfo.FileName = PdfFilePrinter.adobeReaderPath;
            string args = String.Format("/t \"{0}\" \"{1}\"", this.pdfFileName, this.printerName);
            //Debug.WriteLine(args);
            startInfo.Arguments = args;
            startInfo.CreateNoWindow = true;
            startInfo.ErrorDialog = false;
            startInfo.UseShellExecute = false;
            if (this.workingDirectory != null && this.workingDirectory.Length != 0)
                startInfo.WorkingDirectory = this.workingDirectory;

            Process process = Process.Start(startInfo);
            if (!process.WaitForExit(milliseconds))
            {
                // Kill Adobe Reader/Acrobat
                process.Kill();
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    /// <summary>
    /// For reasons only Adobe knows the Reader seams to open and shows the document instead of printing it
    /// when it was not already running.
    /// If you use PDFsharp and have any suggestions to circumvent this function, please let us know.
    /// </summary>
    void DoSomeVeryDirtyHacksToMakeItWork()
    {
        if (PdfFilePrinter.runningAcro != null)
        {
            if (!PdfFilePrinter.runningAcro.HasExited)
                return;
            PdfFilePrinter.runningAcro.Dispose();
            PdfFilePrinter.runningAcro = null;
        }
        // Is any Adobe Reader/Acrobat running?
        Process[] processes = Process.GetProcesses();
        int count = processes.Length;
        for (int idx = 0; idx < count; idx++)
        {
            try
            {
                Process process = processes[idx];
                ProcessModule module = process.MainModule;

                if (String.Compare(Path.GetFileName(module.FileName), Path.GetFileName(PdfFilePrinter.adobeReaderPath), true) == 0)
                {
                    // Yes: Fine, we can print.
                    PdfFilePrinter.runningAcro = process;
                    break;
                }
            }
            catch { }
        }
        if (PdfFilePrinter.runningAcro == null)
        {
            // No: Start an Adobe Reader/Acrobat.
            // If you are within ASP.NET, good luck...
            PdfFilePrinter.runningAcro = Process.Start(PdfFilePrinter.adobeReaderPath);
            PdfFilePrinter.runningAcro.WaitForInputIdle();
        }
    }
    static Process runningAcro;

    /// <summary>
    /// Gets or sets the Adobe Reader or Adobe Acrobat path.
    /// A typical name looks like 'C:\Program Files\Adobe\Adobe Reader 7.0\AcroRd32.exe'.
    /// </summary>
    static public string AdobeReaderPath
    {
        get { return PdfFilePrinter.adobeReaderPath; }
        set { PdfFilePrinter.adobeReaderPath = value; }
    }
    static string adobeReaderPath;

    /// <summary>
    /// Gets or sets the name of the default printer. A typical name looks like '\\myserver\HP LaserJet PCL5'.
    /// </summary>
    static public string DefaultPrinterName
    {
        get { return PdfFilePrinter.defaultPrinterName; }
        set { PdfFilePrinter.defaultPrinterName = value; }
    }
    static string defaultPrinterName;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top