次の方法で共有


方法: XPS ファイルをプログラムにより印刷する

AddJob メソッドの 1 つのオーバーロードを使用して、PrintDialog、または原則として一切のユーザー インターフェイス (UI) を開かずに、XML Paper Specification (XPS) ファイルを印刷することができます。

また、多くの XpsDocumentWriter.Write および XpsDocumentWriter.WriteAsync メソッドを使用して XPS ファイルを印刷することもできます。 詳細については、「XPS ドキュメントの印刷」を参照してください。

XPS を印刷するもう 1 つの方法は、PrintDialog.PrintDocument または PrintDialog.PrintVisual メソッドを使用することです。 印刷ダイアログ ボックスの呼び出しに関するページをご覧ください。

3 つのパラメーターの AddJob(String, String, Boolean) メソッドを使用する主な手順は次のとおりです。 詳細は、下記の例に示します。

  1. プリンターが XPSDrv プリンターかどうかを確認します XPSDrv の詳細については、「印刷の概要」を参照してください。

  2. プリンターが XPSDrv プリンターでない場合は、スレッドのアパートメントをシングル スレッドに設定します。

  3. プリント サーバーと印刷キューのオブジェクトをインスタンス化します。

  4. ジョブ名、印刷するファイル、プリンターが XPSDrv プリンターであるかどうかを示す Boolean フラグを指定して、メソッドを呼び出します。

次の例は、ディレクトリ内のすべての XPS ファイルをバッチ印刷する方法を示しています。 アプリケーションはディレクトリを指定するようにユーザーに要求しますが、3 つのパラメーターの AddJob(String, String, Boolean) メソッドにはユーザー インターフェイス (UI) は必要ありません。 このメソッドは、これに渡すことができる XPS ファイル名とパスが記述された任意のコード パスで使用できます。

AddJob の 3 つのパラメーターの AddJob(String, String, Boolean) オーバーロードは、Boolean パラメーターが false のとき (XPSDrv 以外のプリンターを使用する場合は必須) は常に 1 つのスレッド アパートメントで実行する必要があります。 ただし、.NET の既定のアパートメント状態は、複数のスレッドです。 この例では XPSDrv 以外のプリンターを前提にしているため、この既定の状態を逆にする必要があります。

既定の状態を変更する方法は 2 つあります。 1 つの方法は、アプリケーションの Main メソッドの最初の行 (通常は "static void Main(string[] args)") のすぐ上に、STAThreadAttribute (つまり "[System.STAThreadAttribute()]") を追加するだけです。 しかし、多くのアプリケーションでは、Main メソッドのアパートメント状態はマルチスレッドである必要があります。2 つ目の方法があるのはこのためです。この方法では、SetApartmentState でアパートメント状態を STA に設定した別のスレッドに、AddJob(String, String, Boolean) の呼び出しを配置します。 次の例では、この 2 番目の方法を使用します。

そのため、この例では、まず、Thread オブジェクトをインスタンス化し、それを ThreadStart パラメーターとして PrintXPS メソッドに渡します (PrintXPS メソッドは、例の後半で定義されます)。次に、そのスレッドをシングル スレッド アパートメントに設定します。 それ以降の Main メソッドのコードは、この新しいスレッドを開始します。

この例の要点は、staticstaticBatchXPSPrinter.PrintXPS メソッド内にあります。 このメソッドは、プリント サーバーとキューを作成した後、XPS ファイルを含むディレクトリを指定するようにユーザーに要求します。 ディレクトリの有無と、そのディレクトリに *.xps ファイルがあるかどうかを確認した後、各ファイルが印刷キューに追加されます。 この例では、プリンターが XPSDrv 以外であることを前提としているため、AddJob(String, String, Boolean) メソッドの最後のパラメーターに falseを渡しています。 このため、このメソッドはファイル内の XPS マークアップを検証してから、それをプリンターのページ記述言語に変換することを試みます。 検証に失敗すると、例外がスローされます。 このコード例では、その例外をキャッチし、ユーザーに例外の発生を通知した後、次の 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

XPSDrv プリンターを使用している場合は、最後のパラメーターを true に設定できます。 その場合、XPS はプリンターのページ記述言語であるため、メソッドはファイルの検証や別のページ記述言語への変換を行わずにファイルをプリンターに送信します。 設計時に、アプリケーションが XPSDrv プリンターを使用するかどうかがわからない場合は、IsXpsDevice プロパティを読み込んで、その検出内容に従って分岐するようにアプリケーションを変更できます。

Windows Vista および Microsoft .NET Framework のリリースの直後は、利用できる XPSDrv プリンターが少ないため、XPSDrv プリンター以外のプリンターを XPSDrv プリンターとして偽装することが必要な場合があります。 そのためには、アプリケーションを実行しているコンピューターで、以下のレジストリ キーのファイルの一覧に Pipelineconfig.xml を追加します。

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

ここで、<PseudoXPSPrinter> は任意の印刷キューです。 その後、コンピューターを再起動する必要があります。

このような偽装により、例外を発生させることなく、AddJob(String, String, Boolean) の最後のパラメーターとして true を渡すことができます。ただし、<PseudoXPSPrinter> は実際には XPSDrv プリンターではないため、ガベージのみが印刷されます。

注意

上記の例では、わかりやすくするために、*.xps 拡張子の有無で、ファイルが XPS であるかどうかをテストしていますが、 XPS ファイルに、この拡張子を付ける必要はありません。 isXPS.exe (isXPS 適合性ツール) は、ファイルが XPS に適合しているかどうかをテストする 1 つの方法です。

関連項目