다음을 통해 공유


방법: 프로그래밍 방식으로 XPS 파일 인쇄

AddJob 메서드의 오버로드 하나를 사용하여 PrintDialog 또는 원칙적으로 UI(사용자 인터페이스)를 열지 않고도 XPS(XML Paper Specification) 파일을 인쇄할 수 있습니다.

여러 XpsDocumentWriter.WriteXpsDocumentWriter.WriteAsync 메서드를 사용하여 XPS 파일을 인쇄할 수도 있습니다. 자세한 내용은 XPS 문서 인쇄를 참조하세요.

XPS를 인쇄하는 또 다른 방법은 PrintDialog.PrintDocument 또는 PrintDialog.PrintVisual 메서드를 사용하는 것입니다. 인쇄 호출 대화 상자를 참조하세요.

예제

세 개의 매개 변수 AddJob(String, String, Boolean) 메서드를 사용하는 주요 단계는 다음과 같습니다. 아래 예제에서 자세히 설명합니다.

  1. 프린터가 XPSDrv 프린터인지 확인합니다. XPSDrv에 대한 자세한 내용은 인쇄 개요를 참조하세요.

  2. 프린터가 XPSDrv 프린터가 아닌 경우 스레드 아파트를 단일 스레드로 설정합니다.

  3. 인쇄 서버 및 인쇄 대기열 개체를 인스턴스화합니다.

  4. 작업 이름, 인쇄할 파일 및 프린터가 XPSDrv 프린터인지 여부를 나타내는 Boolean 플래그를 지정하여 메서드를 호출합니다.

아래 예제에서는 디렉터리에서 XPS 파일을 모두 일괄 처리 인쇄하는 방법을 보여 줍니다. 애플리케이션에서 사용자에게 디렉터리를 지정하라는 메시지를 표시하지만 세 개의 매개 변수 AddJob(String, String, Boolean) 메서드에는 UI(사용자 인터페이스)가 필요하지 않습니다. XPS 파일 이름과 전달할 수 있는 경로가 있는 모든 코드 경로에서 사용할 수 있습니다.

AddJob의 세 가지 매개 변수 AddJob(String, String, Boolean) 오버로드는 Boolean 매개 변수가 false일 때마다 단일 스레드 아파트에서 실행해야 합니다. 이 때는 XPSDrv가 아닌 프린터를 사용하는 경우여야 합니다. 그러나 .NET의 기본 아파트 상태는 다중 스레드입니다. 이 예제에서 XPSDrv가 아닌 프린터를 가정하므로 이 기본값을 뒤집어야 합니다.

두 가지 방법으로 기본값을 변경할 수 있습니다. 한 가지 방법은 애플리케이션의 Main 메서드(일반적으로 "static void Main(string[] args)")의 첫 번째 줄 바로 위에 STAThreadAttribute(즉, "[System.STAThreadAttribute()]")를 추가하는 것입니다. 그러나 여러 애플리케이션에서는 Main 메서드에 다중 스레드 아파트 상태가 있어야 하므로 두 번째 방법이 있습니다. AddJob(String, String, Boolean)에 대한 호출을 SetApartmentState를 사용하여 아파트 상태가 STA로 설정된 별도의 스레드에 넣는 것입니다. 아래 예제에서는 두 번째 방법을 사용합니다.

따라서 예제는 Thread 개체를 인스턴스화하고 PrintXPS 메서드를 ThreadStart 매개 변수로 전달하는 것으로 시작합니다. (PrintXPS 메서드는 예제의 뒷부분에서 정의됩니다.) 다음으로 스레드는 단일 스레드 아파트로 설정됩니다. Main 메서드의 나머지 코드는 새 스레드를 시작합니다.

예제의 핵심은 staticBatchXPSPrinter.PrintXPS 메서드에 있습니다. 인쇄 서버와 인쇄 대기열을 만든 후에 이 메서드는 사용자에게 XPS 파일을 포함하는 디렉터리를 묻는 메시지를 표시합니다. 디렉터리의 존재 및 *.xps 파일의 존재의 유효성을 검사한 후에 메서드는 인쇄 대기열에 이러한 각 파일을 추가합니다. 이 예제에서는 프린터가 XPSDrv가 아니라고 가정하므로 falseAddJob(String, String, Boolean) 메서드의 마지막 매개 변수에 전달합니다. 이런 이유로 메서드는 프린터의 페이지 설명 언어로 변환하도록 시도하기 전에 파일에서 XPS 표시의 유효성을 검사합니다. 유효성 검사에 실패하면 예외가 throw됩니다. 예제 코드는 예외를 catch하고 사용자에게 알린 후에 계속해서 다음 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 유효성을 검사하기 위해 파일을 테스트하는 한 가지 방법입니다.

참고 항목