Compartir a través de


Cómo: Imprimir mediante programación archivos XPS

Puede utilizar una sobrecarga del método AddJob para imprimir archivos XML Paper Specification (XPS) sin abrir un control PrintDialog o, en principio, ninguna user interface (UI) en absoluto.

También puede imprimir archivos XML Paper Specification (XPS) usando los diversos métodos Write y WriteAsync de la clase XpsDocumentWriter. Para ver más información sobre este tema, Printing an XPS Document.

Otra manera de imprimir XML Paper Specification (XPS) es utilizar los métodos PrintDocument o PrintVisual del control PrintDialog. Vea Cómo: Invocar un cuadro de diálogo de impresión.

Ejemplo

Los pasos principales para utilizar el método de tres parámetros AddJob(String, String, Boolean) son los siguientes. El ejemplo siguiente proporciona información detallada.

  1. Determine si la impresora es una impresora XPSDrv. (Vea Información general sobre impresión para obtener más información sobre XPSDrv.)

  2. Si la impresora no es una impresora XPSDrv, establezca el estado de subprocesamiento en un subproceso único.

  3. Cree una instancia de un servidor de impresión e imprima el objeto de cola.

  4. Llame al método especificando un nombre de trabajo, el archivo que se va a imprimir y un marcador Boolean que indique si la impresora es una impresora XPSDrv o no.

El ejemplo siguiente muestra cómo imprimir por lotes todos los archivos XPS de un directorio. Aunque la aplicación pide al usuario que especifique el directorio, el método de tres parámetros AddJob(String, String, Boolean) no requiere una user interface (UI). Se puede utilizar en cualquier ruta de acceso de código donde tenga un nombre de archivo XPS y una ruta de acceso que puede pasarle.

La sobrecarga AddJob(String, String, Boolean) de tres parámetros de AddJob se debe ejecutar en un subprocesamiento controlado simple cada vez que el parámetro Boolean sea false, que debe ser cuando se utilice una impresora que no sea XPSDrv. Sin embargo, el estado de subprocesamiento predeterminado para Microsoft .NET es de varios subprocesos. Esta opción predeterminada se debe invertir, dado que el ejemplo asume que se trata de una impresora que no es XPSDrv.

Hay dos maneras de cambiar el valor predeterminado. Una consiste en agregar simplemente STAThreadAttribute (es decir, "[System.STAThreadAttribute()]") inmediatamente encima de la primera línea del método Main de la aplicación (habitualmente, "static void Main(string[] args)"). Sin embargo, muchas aplicaciones requieren que el método Main tenga un estado subprocesamiento múltiple, así que hay un segundo método: coloque la llamada a AddJob(String, String, Boolean) en un subproceso independiente cuyo estado subprocesamiento esté establecido en STA con SetApartmentState. En el ejemplo siguiente se utiliza esta segunda técnica.

Consecuentemente, el ejemplo comienza creando una instancia de un objeto Thread y pasándole un método PrintXPS como parámetro ThreadStart. (El método PrintXPS se define más adelante en el ejemplo.) A continuación, el subproceso se establece en un subprocesamiento controlado simple. El único código restante del método Main inicia el nuevo subproceso.

La parte interesante del ejemplo está en el método static BatchXPSPrinter.PrintXPS. Después de crear un servidor y una cola de impresión, el método pide al usuario un directorio que contenga los archivos XPS. Después de validar la existencia del directorio y la presencia en él de archivos *.xps, el método agrega cada uno de los archivos a la cola de impresión. En el ejemplo se supone que la impresora no es XPSDrv, por lo que estamos pasando false al último parámetro del método AddJob(String, String, Boolean). Por esta razón, el método validará el marcado XPS del archivo antes de intentar convertirlo al lenguaje de descripción de páginas de la impresora. Si se produce un error de validación, se genera una excepción. El código de ejemplo detectará la excepción, se la notificará al usuario y, a continuación, continuará procesando el archivo XPS siguiente.

    Friend Class Program
        <System.MTAThreadAttribute()>
        Shared Sub Main(ByVal args() As String) ' Added for clarity, but this line is redundant because MTA is the default.
            ' Create the secondary thread and pass the printing method for 
            ' the constructor's ThreadStart delegate parameter. The BatchXPSPrinter
            ' class is defined below.
            Dim printingThread As New Thread(AddressOf BatchXPSPrinter.PrintXPS)

            ' Set the thread that will use PrintQueue.AddJob to single threading.
            printingThread.SetApartmentState(ApartmentState.STA)

            ' Start the printing thread. The method passed to the Thread 
            ' constructor will execute.
            printingThread.Start()

        End Sub 'end Main

    End Class 'end Program class

    Public Class BatchXPSPrinter
        Public Shared Sub PrintXPS()
            ' Create print server and print queue.
            Dim localPrintServer As New LocalPrintServer()
            Dim defaultPrintQueue As PrintQueue = LocalPrintServer.GetDefaultPrintQueue()

            ' Prompt user to identify the directory, and then create the directory object.
            Console.Write("Enter the directory containing the XPS files: ")
            Dim directoryPath As String = Console.ReadLine()
            Dim dir As New DirectoryInfo(directoryPath)

            ' If the user mistyped, end the thread and return to the Main thread.
            If Not dir.Exists Then
                Console.WriteLine("There is no such directory.")
            Else
                ' If there are no XPS files in the directory, end the thread 
                ' and return to the Main thread.
                If dir.GetFiles("*.xps").Length = 0 Then
                    Console.WriteLine("There are no XPS files in the directory.")
                Else
                    Console.WriteLine(vbLf & "Jobs will now be added to the print queue.")
                    Console.WriteLine("If the queue is not paused and the printer is working, jobs will begin printing.")

                    ' Batch process all XPS files in the directory.
                    For Each f As FileInfo In dir.GetFiles("*.xps")
                        Dim nextFile As String = directoryPath & "\" & f.Name
                        Console.WriteLine("Adding {0} to queue.", nextFile)

                        Try
                            ' Print the Xps file while providing XPS validation and progress notifications.
                            Dim xpsPrintJob As PrintSystemJobInfo = defaultPrintQueue.AddJob(f.Name, nextFile, False)
                        Catch e As PrintJobException
                            Console.WriteLine(vbLf & vbTab & "{0} could not be added to the print queue.", f.Name)
                            If e.InnerException.Message = "File contains corrupted data." Then
                                Console.WriteLine(vbTab & "It is not a valid XPS file. Use the isXPS Conformance Tool to debug it.")
                            End If
                            Console.WriteLine(vbTab & "Continuing with next XPS file." & vbLf)
                        End Try

                    Next f ' end for each XPS file

                End If 'end if there are no XPS files in the directory

            End If 'end if the directory does not exist

            Console.WriteLine("Press Enter to end program.")
            Console.ReadLine()

        End Sub ' end PrintXPS method

    End Class ' end BatchXPSPrinter class
class Program
{
    [System.MTAThreadAttribute()] // Added for clarity, but this line is redundant because MTA is the default.
    static void Main(string[] args)
    {
        // Create the secondary thread and pass the printing method for 
        // the constructor's ThreadStart delegate parameter. The BatchXPSPrinter
        // class is defined below.
        Thread printingThread = new Thread(BatchXPSPrinter.PrintXPS);

        // Set the thread that will use PrintQueue.AddJob to single threading.
        printingThread.SetApartmentState(ApartmentState.STA);

        // Start the printing thread. The method passed to the Thread 
        // constructor will execute.
        printingThread.Start();

    }//end Main

}//end Program class

public class BatchXPSPrinter
{
    public static void PrintXPS()
    {
        // Create print server and print queue.
        LocalPrintServer localPrintServer = new LocalPrintServer();
        PrintQueue defaultPrintQueue = LocalPrintServer.GetDefaultPrintQueue();

        // Prompt user to identify the directory, and then create the directory object.
        Console.Write("Enter the directory containing the XPS files: ");
        String directoryPath = Console.ReadLine();
        DirectoryInfo dir = new DirectoryInfo(directoryPath);

        // If the user mistyped, end the thread and return to the Main thread.
        if (!dir.Exists)
        {
            Console.WriteLine("There is no such directory.");
        }
        else
        {
            // If there are no XPS files in the directory, end the thread 
            // and return to the Main thread.
            if (dir.GetFiles("*.xps").Length == 0)
            {
                Console.WriteLine("There are no XPS files in the directory.");
            }
            else
            {
                Console.WriteLine("\nJobs will now be added to the print queue.");
                Console.WriteLine("If the queue is not paused and the printer is working, jobs will begin printing.");

                // Batch process all XPS files in the directory.
                foreach (FileInfo f in dir.GetFiles("*.xps"))
                {
                    String nextFile = directoryPath + "\\" + f.Name;
                    Console.WriteLine("Adding {0} to queue.", nextFile);

                    try
                    {
                        // Print the Xps file while providing XPS validation and progress notifications.
                        PrintSystemJobInfo xpsPrintJob = defaultPrintQueue.AddJob(f.Name, nextFile, false);
                    }
                    catch (PrintJobException e)
                    {
                        Console.WriteLine("\n\t{0} could not be added to the print queue.", f.Name);
                        if (e.InnerException.Message == "File contains corrupted data.")
                        {
                            Console.WriteLine("\tIt is not a valid XPS file. Use the isXPS Conformance Tool to debug it.");
                        }
                        Console.WriteLine("\tContinuing with next XPS file.\n");
                    }

                }// end for each XPS file

            }//end if there are no XPS files in the directory

        }//end if the directory does not exist

        Console.WriteLine("Press Enter to end program.");
        Console.ReadLine();

    }// end PrintXPS method

}// end BatchXPSPrinter class

Si está utilizando una impresora XPSDrv, puede establecer el parámetro final en true. En ese caso, dado que XPS es el lenguaje de descripción de páginas de la impresora, el método enviará el archivo a la impresora sin validarlo ni convertirlo a otro lenguaje de descripción de páginas. Si no sabe con seguridad en tiempo de diseño si la aplicación utilizará una impresora XPSDrv, puede modificar la aplicación para que lea la propiedad IsXpsDevice y se bifurque en función de lo que encuentre.

Dado que inicialmente habrá pocas impresoras XPSDrv disponibles inmediatamente después del lanzamiento de Windows Vista y Microsoft .NET Framework, quizá deba hacer que las impresoras que no sean XPSDrv aparezcan como XPSDrv. Para ello, agregue Pipelineconfig.xml a la lista de archivos de la siguiente clave del Registro del equipo donde se ejecute la aplicación:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Environments\Windows NT x86\Drivers\Version-3\<PseudoXPSPrinter>\DependentFiles

donde <PseudoXPSPrinter> es cualquier cola de impresión. A continuación se debe reiniciar el equipo.

Este camuflaje le permitirá pasar true como último parámetro final de AddJob(String, String, Boolean) sin producir una excepción, pero dado que <PseudoXPSPrinter> no es realmente una impresora XPSDrv, sólo se imprimirá basura.

Nota   Para simplificar, el ejemplo anterior utiliza la presencia de una extensión *.xps como prueba de que un archivo es XPS. Sin embargo, los archivos XPS no tienen necesariamente esta extensión. isXPS.exe (Herramienta isXPS Conformance) es un medio de probar la validez XPS de un archivo.

Vea también

Tareas

Printing an XPS Document

Referencia

PrintQueue

AddJob

ApartmentState

STAThreadAttribute

Conceptos

Subprocesamiento administrado y no administrado

isXPS.exe (Herramienta isXPS Conformance)

Documentos en WPF

Información general sobre impresión

Otros recursos

XPS