방법: 프로그래밍 방식으로 XPS 파일 인쇄
AddJob 메서드의 한 오버로드를 사용하면 PrintDialog를 열거나 원칙적으로 어떠한 user interface (UI)도 열 필요 없이 XML Paper Specification (XPS) 파일을 인쇄할 수 있습니다.
또한 XpsDocumentWriter의 많은 Write 및 WriteAsync 메서드를 사용하여 XML Paper Specification (XPS) 파일을 인쇄할 수 있습니다. 자세한 내용은 Printing an XPS Document를 참조하십시오.
XML Paper Specification (XPS)를 인쇄하는 또 다른 방법은 PrintDialog 컨트롤의 PrintDocument 또는 PrintVisual 메서드를 사용하는 것입니다. 방법: 인쇄 대화 상자 호출를 참조하십시오.
예제
세 개 매개 변수의 AddJob(String, String, Boolean) 메서드를 사용하는 주요 단계는 다음과 같습니다. 아래 예제에서 자세한 내용을 제공합니다.
프린터가 XPSDrv 프린터인지 확인합니다. XPSDrv에 대한 자세한 내용은 인쇄 개요를 참조하십시오.
프린터가 XPSDrv 프린터가 아닌 경우 스레드의 아파트를 단일 스레드로 설정합니다.
프린터 서버를 인스턴스화하고 큐 개체를 인쇄합니다.
메서드를 호출하여 작업 이름, 인쇄할 파일 및 프린터가 XPSDrv 프린터인지 여부를 나타내는 Boolean 플래그를 지정합니다.
아래 예제에서는 디렉터리에 있는 모든 XPS 파일을 일괄 인쇄하는 방법을 보여 줍니다. 디렉터리를 지정하라는 메시지를 응용 프로그램에서 표시하지만 세 개 매개 변수의 AddJob(String, String, Boolean) 메서드에는 user interface (UI)가 필요하지 않습니다. 전달할 수 있는 XPS 파일 이름과 경로가 있는 모든 코드 경로에서 이 메서드를 사용할 수 있습니다.
AddJob의 세 개 매개 변수 AddJob(String, String, Boolean) 오버로드는 Boolean 매개 변수가 false(XPSDrv 형식이 아닌 프린터가 사용될 경우에 해당)일 때마다 단일 스레드 아파트에서 실행되어야 합니다. 그러나 Microsoft .NET의 기본 아파트 상태는 다중 스레드입니다. 예제에서는 XPSDrv 형식이 아닌 프린터를 가정하므로 이 기본값을 바꾸어야 합니다.
기본값을 변경하는 두 가지 방법이 있습니다. 한 가지 방법은 단순히 응용 프로그램의 Main 메서드(대개 "static void Main(string[] args)") 바로 위 줄에 STAThreadAttribute(즉, "[System.STAThreadAttribute()]")를 추가하는 것입니다. 그러나 대부분의 응용 프로그램에서는 Main 메서드가 다중 스레드 아파트 상태를 가져야 하므로 이와 다른 두 번째 방법이 있습니다. 두 번째 방법은 SetApartmentState를 사용하여 아파트 상태가 STA로 설정되는 별개의 스레드에 AddJob(String, String, Boolean) 호출을 두는 것입니다. 다음 예제에서는 두 번째 기술을 사용합니다.
따라서 이 예제에서는 먼저 Thread 개체를 인스턴스화하고 PrintXPS 메서드를 ThreadStart 매개 변수로 전달합니다. PrintXPS 메서드는 이 예제의 뒤에서 정의됩니다. 그런 다음 스레드가 단일 스레드 아파트로 설정됩니다. Main 메서드의 나머지 코드만 새 스레드를 시작합니다.
이 예제의 핵심은 static BatchXPSPrinter.PrintXPS 메서드에 있습니다. 인쇄 서버 및 큐를 만든 후에 이 메서드는 XPS 파일이 포함된 디렉터리를 묻는 메시지를 표시합니다. 디렉터리와 디렉터리에 있는 *.xps 파일의 존재를 확인한 후 이 메서드는 이러한 각 파일을 인쇄 큐에 추가합니다. 이 예제에서는 프린터가 XPSDrv가 아니라고 가정하므로 AddJob(String, String, Boolean) 메서드의 마지막 매개 변수에 false를 전달합니다. 이러한 이유 때문에 이 메서드는 파일의 XPS 태그를 프린터의 페이지 설명 언어로 변환하기 전에 유효성을 검사합니다. 유효성 검사가 실패하면 예외가 throw됩니다. 예제 코드는 예외를 catch하고 사용자에게 이를 알린 다음 계속해서 다음 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>*는 임의의 인쇄 큐입니다. 그런 다음 컴퓨터를 다시 시작해야 합니다.
이 가장을 사용하면 예외를 일으키지 않고 true를 AddJob(String, String, Boolean)의 최종 매개 변수로 전달할 수 있지만 *<PseudoXPSPrinter>*가 실제로 XPSDrv 프린터가 아니므로 가비지만 인쇄됩니다.
참고 편의상 위 예제에서는 *.xps 확장명의 존재 여부를 파일이 XPS인지 여부의 테스트로 사용합니다. 그러나 XPS 파일은 이 확장명을 가질 필요가 없습니다. isXPS.exe(isXPS 규칙 도구)는 파일에서 XPS 유효성을 테스트하는 한 방법입니다.