Gewusst wie: Programmgesteuertes Drucken von XPS-Dateien

Aktualisiert: November 2007

Sie können mit einer Überladung der AddJob-Methode XML Paper Specification (XPS)-Dateien drucken, ohne einen PrintDialog bzw. überhaupt eine Benutzeroberfläche (user interface, UI) zu öffnen.

Sie können XML Paper Specification (XPS)-Dateien auch mit den vielen Write-Methoden und den WriteAsync-Methoden von XpsDocumentWriter drucken. Weitere Informationen hierzu finden Sie unter Drucken eines XPS-Dokuments.

Eine andere Art, XML Paper Specification (XPS) zu drucken, ist die Verwendung der PrintDocument-Methode oder der PrintVisual-Methode des PrintDialog-Steuerelements. Weitere Informationen finden Sie unter Gewusst wie: Aufrufen eines Druckdialogfelds.

Beispiel

Im Folgenden finden Sie die wichtigsten Schritte zur Verwendung der dreiparametrigen AddJob(String, String, Boolean)-Methode. Details finden sich im unten stehenden Beispiel.

  1. Stellen Sie fest, ob es sich bei dem Drucker um einen XPSDrv-Drucker handelt. (Weitere Informationen über XPSDrv finden Sie unter Übersicht über das Drucken.)

  2. Wenn es sich bei dem Drucker nicht um einen XPSDrv-Drucker handelt, legen Sie das Apartment des Threads auf Singlethread fest.

  3. Instanziieren Sie einen Druckerserver und ein Druckwarteschlangenobjekt.

  4. Rufen Sie unter Angabe eines Auftragnamens die Methode, die zu druckende Datei und ein Boolean-Flag auf, das angibt, ob es sich bei dem Drucker um einen XPSDrv-Drucker handelt.

Im folgenden Beispiel wird gezeigt, wie alle XPS-Dateien in einem Verzeichnis als Batch gedruckt werden. Obwohl der Benutzer von der Anwendung aufgefordert wird, das Verzeichnis anzugeben, benötigt die dreiparametrige AddJob(String, String, Boolean)-Methode keine Benutzeroberfläche (user interface, UI). Sie kann in jedem Codepfad verwendet werden, in dem ein XPS-Dateiname und -Pfad vorhanden sind, die an sie übergeben werden können.

Die dreiparametrige AddJob(String, String, Boolean)-Überladung von AddJob muss immer dann in einem Singlethreadapartment ausgeführt werden, wenn der Boolean-Parameter false ist. Dies ist gegeben, wenn kein XPSDrv-Drucker verwendet wird. Mehrere Threads sind jedoch der Standardapartmentzustand für Microsoft .NET. Dieser Standard muss umgekehrt werden, da im Beispiel kein XPSDrv-Drucker angenommen wird.

Es gibt zwei Möglichkeiten, den Standard zu ändern. Eine Möglichkeit besteht darin, einfach das STAThreadAttribute (d. h. "[System.STAThreadAttribute()]") genau über der ersten Zeile der Main-Methode der Anwendung (üblicherweise "static void Main(string[] args)") hinzuzufügen. Allerdings erfordern viele Anwendungen, dass die Main-Methode über einen Multithread-Apartmentzustand verfügt, sodass es eine zweite Möglichkeit gibt: Legen Sie den Aufruf von AddJob(String, String, Boolean) in einem separaten Thread ab, dessen Apartmentzustand mithilfe von SetApartmentState auf STA festgelegt wird. Im folgenden Beispiel wird dieses zweite Verfahren verwendet.

Das Beispiel beginnt entsprechend mit der Instanziierung eines Thread-Objekts und der Übergabe einer PrintXPS-Methode als ThreadStart-Parameter. (Die PrintXPS-Methode wird später im Beispiel definiert.) Danach wird der Thread auf ein Singlethreadapartment festgelegt. Mit dem verbleibenden Code der Main-Methode wird der neue Thread gestartet.

Der Hauptbestandteil des Beispiels steckt in der static BatchXPSPrinter.PrintXPS-Methode. Nach dem Erstellen eines Druckerservers und einer Druckwarteschlange wird der Benutzer von der Methode aufgefordert, ein Verzeichnis anzugeben, das XPS-Dateien enthält. Nachdem überprüft wurde, ob das Verzeichnis vorhanden ist und XPS-Dateien enthält, fügt die Methode der Druckwarteschlange jede dieser Dateien hinzu. Im Beispiel wird angenommen, dass es sich bei dem Drucker nicht um einen XPSDrv-Drucker handelt, sodass false an den letzten Parameter der AddJob(String, String, Boolean)-Methode übergeben wird. Aus diesem Grund überprüft die Methode das XPS-Markup in der Datei, bevor sie versucht, es in die Seitenbeschreibungssprache des Druckers umzuwandeln. Wenn die Validierung fehlschlägt, wird eine Ausnahme ausgelöst. Im Beispielcode wird die Ausnahme abgefangen, der Benutzer wird darüber benachrichtigt, und anschließend wird die nächste XPS-Datei verarbeitet.

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

Wenn Sie einen XPSDrv-Drucker verwenden, können Sie den abschließenden Parameter auf true festlegen. Da XPS die Seitenbeschreibungssprache des Druckers ist, sendet in diesem Fall die Methode die Datei ohne Überprüfung oder Umwandlung in eine andere Seitenbeschreibungssprache an den Drucker. Wenn Sie zur Entwurfszeit unsicher sind, ob die Anwendung einen XPSDrv-Drucker verwendet, können Sie die Anwendung so ändern, dass sie die IsXpsDevice-Eigenschaft liest, und abhängig vom Ergebnis eine Verzweigung ausführt.

Da unmittelbar nach der Veröffentlichung von Windows Vista und Microsoft .NET Framework nur wenige XPSDrv-Drucker zur Verfügung stehen werden, müssen Sie Nicht-XPSDrv-Drucker ggf. als XPSDrv-Drucker tarnen. Fügen Sie hierzu auf dem Computer, der die Anwendung ausführt, im folgenden Registrierungsschlüssel die Datei Pipelineconfig.xml zur Liste der Dateien hinzu:

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

wobei <PseudoXPSPrinter> für eine beliebige Druckwarteschlange steht. Der Computer muss anschließend neu gestartet werden.

Mithilfe der Tarnung können Sie true als abschließenden Parameter von AddJob(String, String, Boolean) übergeben, ohne eine Ausnahme auszulösen. Das es sich bei <PseudoXPSPrinter> aber eigentlich nicht um einen XPSDrv-Drucker handelt, werden Sie keine korrekte Druckerausgabe erhalten.

Hinweis   Der Einfachkeit halber gilt im oben stehenden Beispiel das Vorhandensein der Dateinamenserweiterung XPS als Beleg dafür, dass es sich bei einer Datei um eine XPS-Datei handelt XPS-Dateien müssen diese Erweiterung jedoch nicht haben. Das isXPS-Tool für Übereinstimmungstests ist eine Möglichkeit, eine Datei auf XPS-Gültigkeit zu testen.

Siehe auch

Aufgaben

Drucken eines XPS-Dokuments

Konzepte

Verwaltetes und nicht verwaltetes Threading

isXPS-Tool für Übereinstimmungstests

Dokumente in Windows Presentation Foundation

Übersicht über das Drucken

Referenz

PrintQueue

AddJob

ApartmentState

STAThreadAttribute

Weitere Ressourcen

XPS

Beispiele für Drucken