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


Как печатать файлы XPS программным способом

Для печати файлов XML Paper Specification (XPS) можно использовать перегрузку метода AddJob не открывая PrintDialog или, в принципе, вообще user interface (UI).

Кроме того, напечатать файлы XML Paper Specification (XPS) можно с помощью методов Write и WriteAsync объекта XpsDocumentWriter. Для получения дополнительных сведений об этом см. Printing an XPS Document.

Другой способ печати XML Paper Specification (XPS) заключается в использовании методов PrintDocument или PrintVisual элемента управления PrintDialog. См. раздел Практическое руководство. Вызов диалогового окна печати.

Пример

Ниже приведены основные шаги использования метода AddJob(String, String, Boolean) с тремя параметрами. Нижеприведенный пример содержит подробные сведения.

  1. Определите, является ли принтер принтером XPSDrv. (Дополнительные сведения о драйвере XPSDrv см. в разделе Общие сведения о печати.)

  2. Если принтер не является принтером XPSDrv, установите подразделение потока на однопотоковое.

  3. Создайте экземпляр сервера печати и объект очереди печати.

  4. Вызовите метод, указав имя задания, файл для печати и флаг Boolean, указывающий, является ли принтер принтером XPSDrv.

В примере, который приведен ниже, показано, как выполнить пакетную печать всех файлов XPS каталога. Хотя приложение предлагает пользователю указать каталог, метод с тремя параметрами AddJob(String, String, Boolean) не требует user interface (UI). Метод можно использовать в любом пути кода, где присутствуют имя файла XPS и путь, который можно ему передать.

Перегрузка метода AddJob(String, String, Boolean) с тремя параметрами для AddJob должна выполняться в однопотоковом подразделении, когда параметр Boolean принимает значение false, которое он должен принимать при использовании принтера не XPSDrv. Однако по умолчанию состояние подразделения Microsoft .NET является многопотоковым. Это значение по умолчанию должно быть отменено, поскольку в примере предполагается, что используется принтер не XPSDrv.

Существует два способа, чтобы изменить значение по умолчанию. Одним из них является простое добавление STAThreadAttribute (то есть "[System.STAThreadAttribute()]") непосредственно над первой строкой метода Main приложения (обычно, "static void Main(string[] args)"). Однако многие приложения требуют, чтобы метод Main имел состояние многопотокового подразделения, поэтому существует второй метод: помещение вызова метода AddJob(String, String, Boolean) в отдельный поток, состояние подразделения которого установлено значение STA, с методом SetApartmentState. В примере, который приведен ниже, используется этот второй метод.

Соответственно, пример начинается с создания экземпляра объекта Thread и передачи его методу PrintXPS как параметра ThreadStart. (Метод PrintXPS определяется позже в этом примере). Далее поток устанавливается в однопотоковое подразделение. Новый поток запускает только оставшийся код метода Main.

Суть примера содержится в методе static BatchXPSPrinter.PrintXPS. После создания сервера печати и очереди метод предлагает пользователю выбрать каталог, содержащий файлы XPS. После проверки существования каталога и наличия в нем файлов xps метод добавляет каждый такой файл в очередь печати. Предполагается, что принтер не поддерживает XPSDrv, поэтому мы передаем значение false последнему параметру метода AddJob(String, String, Boolean). По этой причине, метод будет проверять разметку XPS в файле перед попыткой преобразования его в язык описания страниц принтера. Если проверка завершилась неудачно, вызывается исключение. Пример кода получит исключение, уведомит о нем пользователя и перейдет к обработке следующего файла XPS.

    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

При использовании принтера XPSDrv можно установить для последнего параметра значение true. В этом случае, поскольку XPS является языком описания страницы принтера, метод отправит файл на принтер без проверки его или преобразования в другой язык описания страниц. Если имеются сомнения во время разработки приложения, что оно будет использовать принтер XPSDrv, можно изменить приложение таким образом, чтобы оно считывало свойство IsXpsDevice и выполняло переход в соответствии с тем, что будет обнаружено.

Поскольку будет существовать изначально несколько принтеров XPSDrv, доступных сразу после выпуска Windows Vista и Microsoft .NET Framework, может потребоваться маскировка принтера не XPSDrv в качестве принтера XPSDrv. Для этого следует добавить файл Pipelineconfig.xml в список файлов в следующем разделе реестра компьютера, на котором запущено приложение:

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

где <PseudoXPSPrinter> — любая очередь печати. Затем необходимо перезагрузить компьютер.

Эта маскировка позволит передать значение true в качестве последнего параметра метода AddJob(String, String, Boolean) без вызова исключения, но поскольку <PseudoXPSPrinter> является не действительным принтером XPSDrv, будет печататься только мусор.

Примечание. Для упрощения, в примере выше используется наличие расширения xps в качестве проверки того, что файлом является XPS. Однако файлам XPS нет необходимости иметь это расширение. isXPS.exe (средство проверки соответствия isXPS) является одним из способов проверки файла на соответствие XPS.

См. также

Задачи

Printing an XPS Document

Ссылки

PrintQueue

AddJob

ApartmentState

STAThreadAttribute

Основные понятия

Управляемые и неуправляемые потоки

isXPS.exe (средство проверки соответствия isXPS)

Документы в WPF

Общие сведения о печати

Другие ресурсы

XPS