Cómo imprimir un archivo XPS (WPF .NET)

A veces necesitará agregar un nuevo trabajo de impresión a la cola de impresión sin abrir un cuadro de diálogo de impresión. Puede usar uno de los métodos PrintQueue.AddJob para hacerlo. Esta es la manera de hacerlo.

Importante

La documentación de la guía de escritorio para .NET 7 y .NET 6 está en proceso de elaboración.

En el ejemplo siguiente usamos el método AddJob(String, String, Boolean), una de las varias sobrecargas de AddJob, para:

  • Agregar un nuevo trabajo de impresión para un documento de especificación de papel XML (XPS) en la cola de impresión predeterminada.
  • Asignar un nombre al nuevo trabajo.
  • Especificar si se debe validar el documento XPS (mediante el parámetro fastCopy).

Cuando se usa el método AddJob(String, String, Boolean), el valor del parámetro fastCopy es una consideración clave:

  • Si establece el parámetro fastCopy en true, se omite la validación de XPS y el trabajo de impresión se pondrá en cola rápidamente sin comentarios de progreso página por página.
  • Si establece el parámetro fastCopy en false, el subproceso que llama al método AddJob debe tener un estado de contenedor uniproceso; de lo contrario, se producirá una excepción. Para obtener más información, vea la sección Comentarios para AddJob(String, String, Boolean).

Agregar nuevos trabajos de impresión a la cola

En este ejemplo se agregan uno o varios documentos XPS a la cola predeterminada. El código hará lo siguiente:

  1. Usar Task.Run para evitar bloquear el subproceso de interfaz de usuario, ya que no hay ninguna versión asincrónica de AddJob.
  2. Ejecutar AddJob(String, String, Boolean) en un subproceso con el estado de contenedor uniproceso si el valor del parámetro fastCopy es false.
  3. Obtener una referencia al valor predeterminado PrintQueue de LocalPrintServer.
  4. Llamar a AddJob(String, String, Boolean) en la referencia de cola de impresión, pasando un nombre de trabajo, una ruta de acceso del documento XPS y el parámetro fastCopy.

Si la cola no está en pausa y la impresora funciona, un trabajo de impresión comenzará a imprimir automáticamente cuando llegue al principio de la cola de impresión.

Sugerencia

Para evitar el cuadro de diálogo Guardar archivo de salida como al agregar un trabajo de impresión a la cola predeterminada, asegúrese de que la impresora predeterminada no sea Escritor de documentos XPS de Microsoft, Microsoft Print to PDF u otras opciones de impresión a archivo.

/// <summary>
/// Asyncronously, add a batch of XPS documents to the print queue using a PrintQueue.AddJob method.
/// Handle the thread apartment state required by the PrintQueue.AddJob method.
/// </summary>
/// <param name="xpsFilePaths">A collection of XPS documents.</param>
/// <param name="fastCopy">Whether to validate the XPS documents.</param>
/// <returns>Whether all documents were added to the print queue.</returns>
public static async Task<bool> BatchAddToPrintQueueAsync(IEnumerable<string> xpsFilePaths, bool fastCopy = false)
{
    bool allAdded = true;

    // Queue some work to run on the ThreadPool.
    // Wait for completion without blocking the calling thread.
    await Task.Run(() =>
    {
        if (fastCopy)
            allAdded = BatchAddToPrintQueue(xpsFilePaths, fastCopy);
        else
        {
            // Create a thread to call the PrintQueue.AddJob method.
            Thread newThread = new(() =>
            {
                allAdded = BatchAddToPrintQueue(xpsFilePaths, fastCopy);
            });

            // Set the thread to single-threaded apartment state.
            newThread.SetApartmentState(ApartmentState.STA);

            // Start the thread.
            newThread.Start();

            // Wait for thread completion. Blocks the calling thread,
            // which is a ThreadPool thread.
            newThread.Join();
        }
    });

    return allAdded;
}

/// <summary>
/// Add a batch of XPS documents to the print queue using a PrintQueue.AddJob method.
/// </summary>
/// <param name="xpsFilePaths">A collection of XPS documents.</param>
/// <param name="fastCopy">Whether to validate the XPS documents.</param>
/// <returns>Whether all documents were added to the print queue.</returns>
public static bool BatchAddToPrintQueue(IEnumerable<string> xpsFilePaths, bool fastCopy)
{
    bool allAdded = true;

    // To print without getting the "Save Output File As" dialog, ensure
    // that your default printer is not the Microsoft XPS Document Writer,
    // Microsoft Print to PDF, or other print-to-file option.

    // Get a reference to the default print queue.
    PrintQueue defaultPrintQueue = LocalPrintServer.GetDefaultPrintQueue();

    // Iterate through the document collection.
    foreach (string xpsFilePath in xpsFilePaths)
    {
        // Get document name.
        string xpsFileName = Path.GetFileName(xpsFilePath);

        try
        {
            // The AddJob method adds a new print job for an XPS
            // document into the print queue, and assigns a job name.
            // Use fastCopy to skip XPS validation and progress notifications.
            // If fastCopy is false, the thread that calls PrintQueue.AddJob
            // must have a single-threaded apartment state.
            PrintSystemJobInfo xpsPrintJob =
                    defaultPrintQueue.AddJob(jobName: xpsFileName, documentPath: xpsFilePath, fastCopy);

            // If the queue is not paused and the printer is working, then jobs will automatically begin printing.
            Debug.WriteLine($"Added {xpsFileName} to the print queue.");
        }
        catch (PrintJobException e)
        {
            allAdded = false;
            Debug.WriteLine($"Failed to add {xpsFileName} to the print queue: {e.Message}\r\n{e.InnerException}");
        }
    }

    return allAdded;
}
''' <summary>
''' Asyncronously, add a batch of XPS documents to the print queue using a PrintQueue.AddJob method.
''' Handle the thread apartment state required by the PrintQueue.AddJob method.
''' </summary>
''' <param name="xpsFilePaths">A collection of XPS documents.</param>
''' <param name="fastCopy">Whether to validate the XPS documents.</param>
''' <returns>Whether all documents were added to the print queue.</returns>
Public Shared Async Function BatchAddToPrintQueueAsync(xpsFilePaths As IEnumerable(Of String), Optional fastCopy As Boolean = False) As Task(Of Boolean)

    Dim isAllPrinted As Boolean = True

    ' Queue some work to run on the ThreadPool.
    ' Wait for completion without blocking the calling thread.
    Await Task.Run(
        Sub()
            If fastCopy Then
                isAllPrinted = BatchAddToPrintQueue(xpsFilePaths, fastCopy)
            Else
                ' Create a thread to call the PrintQueue.AddJob method.
                Dim newThread As New Thread(
                    Sub()
                        isAllPrinted = BatchAddToPrintQueue(xpsFilePaths, fastCopy)
                    End Sub
                )

                ' Set the thread to single-threaded apartment state.
                newThread.SetApartmentState(ApartmentState.STA)

                ' Start the thread.
                newThread.Start()

                ' Wait for thread completion. Blocks the calling thread,
                ' which is a ThreadPool thread.
                newThread.Join()
            End If
        End Sub
    )

    Return isAllPrinted

End Function

''' <summary>
''' Add a batch of XPS documents to the print queue using a PrintQueue.AddJob method.
''' </summary>
''' <param name="xpsFilePaths">A collection of XPS documents.</param>
''' <param name="fastCopy">Whether to validate the XPS documents.</param>
''' <returns>Whether all documents were added to the print queue.</returns>
Public Shared Function BatchAddToPrintQueue(xpsFilePaths As IEnumerable(Of String), fastCopy As Boolean) As Boolean

    Dim isAllPrinted As Boolean = True

    ' To print without getting the "Save Output File As" dialog, ensure
    ' that your default printer is not the Microsoft XPS Document Writer,
    ' Microsoft Print to PDF, or other print-to-file option.

    ' Get a reference to the default print queue.
    Dim defaultPrintQueue As PrintQueue = LocalPrintServer.GetDefaultPrintQueue()

    ' Iterate through the document collection.
    For Each xpsFilePath As String In xpsFilePaths

        ' Get document name.
        Dim xpsFileName As String = Path.GetFileName(xpsFilePath)

        Try
            ' The AddJob method adds a new print job for an XPS
            ' document into the print queue, and assigns a job name.
            ' Use fastCopy to skip XPS validation and progress notifications.
            ' If fastCopy is false, the thread that calls PrintQueue.AddJob
            ' must have a single-threaded apartment state.
            Dim xpsPrintJob As PrintSystemJobInfo = defaultPrintQueue.AddJob(jobName:=xpsFileName, documentPath:=xpsFilePath, fastCopy)

            ' If the queue is not paused and the printer is working, then jobs will automatically begin printing.
            Debug.WriteLine($"Added {xpsFileName} to the print queue.")
        Catch e As PrintJobException
            isAllPrinted = False
            Debug.WriteLine($"Failed to add {xpsFileName} to the print queue: {e.Message}\r\n{e.InnerException}")
        End Try
    Next

    Return isAllPrinted

End Function

Sugerencia

También puede imprimir archivos XPS mediante:

Para obtener más información, consulte Cómo mostrar un cuadro de diálogo de impresión e Información general sobre la impresión de documentos.

Vea también