Comment : imprimer des fichiers XPS par programmation

Vous pouvez utiliser une surcharge de la méthode AddJob pour imprimer des fichiers XML Paper Specification (XPS) sans ouvrir de PrintDialog ni, en principe, aucune user interface (UI).

Vous pouvez également imprimer des fichiers XML Paper Specification (XPS) à l'aide des nombreuses méthodes Write et WriteAsync du XpsDocumentWriter. Pour plus d'informations à ce sujet, Printing an XPS Document.

Une autre façon d'imprimer du XML Paper Specification (XPS) est d'utiliser les méthodesPrintDocument ou PrintVisual du contrôle PrintDialog. Consultez Comment : appeler une boîte de dialogue Imprimer.

Exemple

Les étapes principales à l'utilisation de la méthode des trois paramètres AddJob(String, String, Boolean) sont les suivantes. L'exemple ci-dessous apporte des détails à ce sujet.

  1. Déterminez si l'imprimante est une imprimante XPSDrv. (Consultez Vue d'ensemble de l'impression pour plus d'informations sur XPSDrv.)

  2. Si l'imprimante n'est pas une imprimante XPSDrv, affectez STA (Single Thread Apartment) à l'état de cloisonnement du thread.

  3. Instanciez un serveur d'impression et un objet de la file d'attente à l'impression.

  4. Appelez la méthode, en spécifiant le nom du travail, le fichier à imprimer et un indicateur Boolean qui signale si l'imprimante est une imprimante XPSDrv ou pas.

L'exemple suivant montre comment imprimer par lots tous les fichiers XPS dans un répertoire. Bien que l'application invite l'utilisateur à spécifier le répertoire, la méthode des trois paramètres AddJob(String, String, Boolean) ne requiert pas d'user interface (UI). Elle peut être utilisée dans un chemin d'accès au code dans lequel vous avez un nom de fichier XPS et un chemin d'accès que vous pouvez passer à celui-ci.

La surcharge des trois paramètres AddJob(String, String, Boolean) de AddJob doit s'exécuter dans un thread unique cloisonné (STA) toutes les fois que le paramètre Boolean est false, ce qui doit être le cas lorsqu'une imprimante qui n'est pas une imprimante XPSDrv est utilisée. Toutefois, l'état de cloisonnement par défaut pour Microsoft .NET est plusieurs threads. Cet état par défaut doit être inversé puisque l'exemple illustre une imprimante qui n'est pas une imprimante XPSDrv.

Il existe deux manières de modifier l'état par défaut. L'un des moyens consiste simplement à ajouter STAThreadAttribute (autrement dit, "[System.STAThreadAttribute()]") juste au-dessus de la première ligne de la méthode Main de l'application (habituellement "static void Main(string[] args)"). Toutefois, de nombreuses applications exigent de la méthode Main qu'elle ait un état de cloisonnement multithread, il existe donc une deuxième méthode : placez l'appel à AddJob(String, String, Boolean) dans un thread séparé dont l'état de cloisonnement a la valeur STA avec SetApartmentState. L'exemple suivant utilise cette deuxième technique.

En conséquence, l'exemple commence en instanciant un objet Thread et lui passant une méthode PrintXPS comme paramètre ThreadStart. (La méthode PrintXPS est définie ultérieurement dans l'exemple.) Ensuite, le thread est configuré en thread unique cloisonné (STA). Le seul code restant de la méthode Main démarre le nouveau thread.

L'essentiel de l'exemple se trouve dans la méthode static BatchXPSPrinter.PrintXPS. Après avoir créé un serveur d'impression et une file d'attente, la méthode invite l'utilisateur à entrer un répertoire contenant des fichiers XPS. Après avoir validé l'existence du répertoire et la présence de fichiers *.xps dans celui-ci, la méthode ajoute chacun de ces fichiers à la file d'attente à l'impression. L'exemple supposant que l'imprimante n'est pas une imprimante XPSDrv, nous passons donc false au dernier paramètre de la méthode AddJob(String, String, Boolean). Pour cette raison, la méthode validera le balisage XPS dans le fichier avant d'essayer de le convertir en langage de description de page de l'imprimante. Si la validation échoue, une exception est levée. L'exemple de code interceptera l'exception, notifiera l'utilisateur à son propos, puis passera au traitement du fichier XPS suivant.

    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

Si vous utilisez une imprimante XPSDrv, vous pouvez alors affecter la valeur true au dernier paramètre. Dans ce cas, puisque XPS est le langage de description de page de l'imprimante, la méthode enverra le fichier à l'imprimante sans le valider ou le convertir dans un autre langage. Si vous n'êtes pas certain, au moment du design de savoir si l'application utilisera une imprimante XPSDrv ou pas, vous pouvez modifier l'application pour qu'elle lise la propriété IsXpsDevice et crée une branche en fonction de ce qu'elle trouve.

Puisque initialement peu d'imprimantes XPSDrv seront disponibles immédiatement après la version finale de Windows Vista et de Microsoft .NET Framework, vous pouvez être amené à déguiser une imprimante qui n'est pas une imprimante XPSDrv en imprimante XPSDrv. Pour cela, ajoutez Pipelineconfig.xml à la liste des fichiers dans la clé de Registre suivante de l'ordinateur qui exécute votre application :

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

<PseudoXPSPrinter> est une file d'attente à l'impression quelconque. Puis l'ordinateur doit être redémarré.

Ce déguisement vous permettra de passer true comme dernier paramètre de AddJob(String, String, Boolean) sans provoquer une exception, mais puisque <PseudoXPSPrinter > n'est pas vraiment une imprimante XPSDrv, des informations superflues seront imprimées.

Remarque   Par simplicité, l'exemple ci-dessus utilise la présence d'une extension *.xps pour tester qu'un fichier est XPS. Toutefois, des fichiers XPS peuvent avoir une extension différente. L' isXPS.exe (isXPS Conformance Tool) est un moyen de tester la validité XPS d'un fichier.

Voir aussi

Tâches

Printing an XPS Document

Référence

PrintQueue

AddJob

ApartmentState

STAThreadAttribute

Concepts

Threading managé et non managé

isXPS.exe (isXPS Conformance Tool)

Documents dans WPF

Vue d'ensemble de l'impression

Autres ressources

XPS