Поделиться через


Как распечатать файл XPS (WPF .NET)

Иногда необходимо добавить новое задание печати в очередь печати без открытия диалогового окна печати. Для этого можно использовать один из методов PrintQueue.AddJob. Вот как.

В следующем примере мы используем метод AddJob(String, String, Boolean), один из нескольких перегрузок AddJob, чтобы:

  • Добавьте новое задание печати для документа XML Paper Specification (XPS) в очередь печати по умолчанию.
  • Назовите новое задание.
  • Укажите, следует ли проверять документ XPS (с помощью параметра fastCopy).

При использовании метода AddJob(String, String, Boolean) значение параметра fastCopy является ключевым фактором:

  • Если для параметра fastCopy задано значение true, проверка XPS будет пропущена, а задание печати быстро загрузится без обратной связи о прогрессе по страницам.
  • Если для параметра fastCopy задано значение false, поток, вызывающий метод AddJob, должен иметь состояние однопоточной квартиры, в противном случае будет выброшено исключение. Дополнительные сведения см. в разделе Примечания для AddJob(String, String, Boolean).

Добавление новых заданий печати в очередь

В этом примере в очередь по умолчанию добавляется один или несколько документов XPS. Код будет:

  1. Используйте Task.Run, чтобы избежать блокировки потока пользовательского интерфейса, так как нет асинхронной версии AddJob.
  2. Если значение параметра fastCopy равно false, выполните AddJob(String, String, Boolean) в потоке, находящемся в состоянии однопоточной квартиры с .
  3. Получите ссылку на PrintQueue по умолчанию для LocalPrintServer.
  4. Выполните вызов AddJob(String, String, Boolean) в очереди печати, передав имя задания, путь к документу XPS и параметр fastCopy.

Если очередь не приостановлена и принтер работает, задание печати автоматически начнет печать, когда она достигнет верхней части очереди печати.

Совет

Чтобы избежать диалогового окна Сохранить выходной файл как при добавлении задания на печать в очередь по умолчанию, убедитесь, что принтер по умолчанию не Microsoft XPS Document Writer, Microsoft Print to PDFили другие параметры печати в файл.

/// <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

Совет

Вы также можете распечатать файлы XPS с помощью:

Дополнительные сведения см. в разделе Как отображать диалоговое окно печати и Обзор печати документов.

См. также