Udostępnij przez


Jak za pomocą programowania drukować pliki XPS

Można użyć jednego przeciążenia AddJob metody do drukowania plików specyfikacji papieru XML (XPS) bez otwierania PrintDialog lub, w zasadzie, żadnego interfejsu użytkownika w ogóle.

Można również drukować pliki XPS przy użyciu wielu XpsDocumentWriter.Write metod i XpsDocumentWriter.WriteAsync . Aby uzyskać więcej informacji, zobacz Drukowanie dokumentu XPS.

Innym sposobem drukowania XPS jest użycie PrintDialog.PrintDocument metod lub PrintDialog.PrintVisual . Zobacz Wywoływanie okna dialogowego drukowania.

Przykład

Główne kroki używania metody trzech parametrów AddJob(String, String, Boolean) są następujące. Poniższy przykład zawiera szczegółowe informacje.

  1. Ustal, czy drukarka jest drukarką XPSDrv. Aby uzyskać więcej informacji na temat xpSDrv, zobacz Temat Drukowanie — omówienie .

  2. Jeśli drukarka nie jest drukarką XPSDrv, ustaw mieszkanie wątku na jeden wątek.

  3. Utworzenie wystąpienia serwera wydruku i obiektu kolejki wydruku.

  4. Wywołaj metodę, określając nazwę zadania, plik do wydrukowania i flagę wskazującą Boolean , czy drukarka jest drukarką XPSDrv.

W poniższym przykładzie pokazano, jak wsadować drukowanie wszystkich plików XPS w katalogu. Mimo że aplikacja monituje użytkownika o określenie katalogu, metoda trzech parametrów AddJob(String, String, Boolean) nie wymaga interfejsu użytkownika . Można go używać w dowolnej ścieżce kodu, w której masz nazwę pliku XPS i ścieżkę, którą można przekazać do niego.

Przeciążenie trzech parametrów AddJob(String, String, Boolean)AddJob musi być uruchamiane w jednym mieszkaniu wątku za każdym razem Boolean , gdy parametr ma wartość false, który musi być używany, gdy jest używana drukarka innej niż XPSDrv. Jednak domyślny stan mieszkania dla platformy .NET to wiele wątków. Ta wartość domyślna musi zostać odwrócona, ponieważ w przykładzie przyjęto założenie, że drukarka innej niż XPSDrv.

Istnieją dwa sposoby zmiany wartości domyślnej. Jednym ze sposobów jest po prostu dodanie STAThreadAttribute (czyli "[System.STAThreadAttribute()]") tuż nad pierwszym wierszem metody aplikacji Main (zwykle "static void Main(string[] args)"). Jednak wiele aplikacji wymaga, aby Main metoda miała stan mieszkania wielowątkowego, więc istnieje druga metoda: umieścić AddJob(String, String, Boolean) wywołanie w osobnym wątku, którego stan mieszkania jest ustawiony na STASetApartmentState. W poniższym przykładzie użyto tej drugiej techniki.

W związku z tym przykład rozpoczyna się od utworzenia Thread wystąpienia obiektu i przekazania go metody PrintXPS jako parametru ThreadStart . (Metoda PrintXPS jest zdefiniowana w dalszej części przykładu. Następnie wątek jest ustawiony na jednowątkowy apartament. Jedyny pozostały kod Main metody uruchamia nowy wątek.

Mięso przykładu znajduje się w metodzie staticBatchXPSPrinter.PrintXPS . Po utworzeniu serwera wydruku i kolejki metoda monituje użytkownika o katalog zawierający pliki XPS. Po zweryfikowaniu istnienia katalogu i obecności w nim plików *.xps metoda dodaje każdy taki plik do kolejki wydruku. W tym przykładzie przyjęto założenie, że drukarka nie jest plikiem XPSDrv, dlatego przekazujemy false do ostatniego parametru AddJob(String, String, Boolean) metody. Z tego powodu metoda zweryfikuje znacznik XPS w pliku przed podjęciem próby przekonwertowania go na język opisu strony drukarki. Jeśli walidacja zakończy się niepowodzeniem, zostanie zgłoszony wyjątek. Przykładowy kod przechwyci wyjątek, powiadomi użytkownika o tym, a następnie przejdzie do przetworzenia następnego pliku XPS.

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

Jeśli używasz drukarki XPSDrv, możesz ustawić parametr końcowy na truewartość . W takim przypadku, ponieważ XPS jest językiem opisu strony drukarki, metoda wyśle plik do drukarki bez walidacji lub przekonwertowania go na inny język opisu strony. Jeśli w czasie projektowania nie masz pewności, czy aplikacja będzie używać drukarki XPSDrv, możesz zmodyfikować aplikację, aby odczytać IsXpsDevice właściwość i gałąź zgodnie z tym, co znajdzie.

Ponieważ początkowo będzie kilka drukarek XPSDrv dostępnych natychmiast po wydaniu systemów Windows Vista i Microsoft .NET Framework, może być konieczne ukrycie drukarki innej niż XPSDrv jako drukarki XPSDrv. W tym celu dodaj plik Pipelineconfig.xml do listy plików w następującym kluczu rejestru komputera z uruchomioną aplikacją:

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

gdzie <PseudoXPSPrinter> to dowolna kolejka wydruku. Następnie należy ponownie uruchomić maszynę.

To przebranie umożliwi przekazanie true jako końcowego parametru AddJob(String, String, Boolean) bez spowodowania wyjątku, ale ponieważ <PseudoXPSPrinter> nie jest naprawdę drukarką XPSDrv, tylko śmieci będą drukowane.

Uwaga

Dla uproszczenia w powyższym przykładzie użyto obecności rozszerzenia *.xps jako testu, że plik jest XPS. Jednak pliki XPS nie muszą mieć tego rozszerzenia. IsXPS.exe (isXPS Conformance Tool) to jeden ze sposobów testowania pliku pod kątem ważności XPS.

Zobacz też