方法 : XPS ファイルをプログラムにより印刷する
AddJob メソッドの 1 つのオーバーロードを使用すると、PrintDialog や、原則としてはその他のuser interface (UI) を一切開くことなく、XML Paper Specification (XPS) ファイルを印刷することができます。
また、XpsDocumentWriter の多くの Write メソッドや WriteAsync メソッドを使用して、XML Paper Specification (XPS) ファイルを印刷することもできます。 この詳細については、「XPS ドキュメントの印刷」を参照してください。
XML Paper Specification (XPS) の印刷は、PrintDialog コントロールの PrintDocument メソッドまたは PrintVisual メソッドを使用しても実行できます。 「方法 : 印刷ダイアログ ボックスを呼び出す」を参照してください。
使用例
3 つのパラメーターをとる AddJob(String, String, Boolean) メソッドを使用する主な手順は次のとおりです。 詳細は、下記の例に示します。
プリンターが XPSDrv プリンターであるかどうかを確認します (XPSDrv の詳細については、「印刷の概要」を参照してください)。
プリンターが XPSDrv プリンターでない場合は、スレッドのアパートメントをシングル スレッドに設定します。
プリント サーバーと印刷キューのオブジェクトをインスタンス化します。
ジョブ名、印刷するファイル、およびプリンターが XPSDrv プリンターであるかどうかを示す Boolean フラグを指定して、メソッドを呼び出します。
ディレクトリ内のすべての XPS ファイルをバッチ印刷する方法を次の例に示します。 アプリケーションはユーザーにディレクトリの指定を求めますが、3 つのパラメーターをとる AddJob(String, String, Boolean) メソッドはuser interface (UI) を必要としません。 このメソッドは、そのメソッドに渡すことができる XPS ファイル名とパスが記述された任意のコード パスで使用できます。
AddJob の 3 つのパラメーターをとる AddJob(String, String, Boolean) オーバーロードは、Boolean パラメーターが false の場合 (XPSDrv 以外のプリンターが使用されている場合) は必ずシングル スレッドで実行する必要があります。 ただし、Microsoft .NET の既定のアパートメントの状態は、マルチ スレッドです。 この例では XPSDrv 以外のプリンターを前提にしているため、この既定の状態を逆にする必要があります。
既定の状態を変更する方法は 2 つあります。 1 つは、単純に STAThreadAttribute (つまり "[System.STAThreadAttribute()]") をアプリケーションの Main メソッド (通常は "static void Main(string[] args)") のすぐ上に追加する方法です。 ただし、多くのアプリケーションは、Main メソッドのアパートメントの状態がマルチ スレッドであることを必要とするため、もう 1 つの方法が用意されています。それは、AddJob(String, String, Boolean) の呼び出しを、そのアパートメントの状態が SetApartmentState で STA に設定されている個別のスレッドで行う方法です。 次に示す例では、この 2 番目の方法を使用します。
したがって、この例では、最初に Thread オブジェクトをインスタンス化し、そのオブジェクトを PrintXPS メソッドに ThreadStart パラメーターとして渡します (PrintXPS メソッドは例の後半で定義されます)。次に、そのスレッドをシングル スレッド アパートメントに設定します。 それ以降の Main メソッドのコードでは、この新しいスレッドを開始します。
この例の要点は、static BatchXPSPrinter.PrintXPS メソッド内にあります。 プリント サーバーとキューを作成した後、このメソッドによって、XPS ファイルを含むディレクトリの指定を求めるプロンプトが表示されます。 ディレクトリの有無と、そのディレクトリに *.xps ファイルがあるかどうかを確認した後に、各ファイルが印刷キューに追加されます。 この例では、プリンターが XPSDrv 以外のプリンターであることが前提になっているため、AddJob(String, String, Boolean) メソッドの最後のパラメーターに false を渡しています。 このため、このメソッドはファイル内の 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 プロパティを読み込んで、その検出内容に従って分岐するようにアプリケーションを変更できます。
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 つの手段です。