다음을 통해 공유


UWP 디바이스 앱에서 인쇄 작업을 관리하는 방법

Windows 8.1에서 프린터용 UWP 디바이스 앱은 인쇄 작업을 관리할 수 있습니다. 이 항목에서는 인쇄 작업 관리 및 프린터 기본 테넌트 샘플의 C# 버전을 사용하여 인쇄 작업의 보기를 만들고, 해당 작업을 모니터링하고, 필요한 경우 작업을 취소하는 방법을 보여 줍니다. 일반적으로 UWP 디바이스 앱에 대한 자세한 내용은 UWP 디바이스 앱 모임을 참조 하세요.

인쇄 작업 관리 및 프린터 기본 테넌트 샘플의 C# 버전은 DeviceAppForPrinters2 프로젝트의 DeviceMaintenance.xaml.cs 파일프린터 기본 테넌트를 보여 줍니다. Bidi를 사용하기 위해 샘플에서는 PrinterExtensionLibrary 프로젝트의 프린터 확장 라이브러리를 사용합니다. 프린터 확장 라이브러리는 v4 인쇄 드라이버의 프린터 확장 인터페이스에 액세스하는 편리한 방법을 제공합니다. 자세한 내용은 프린터 확장 라이브러리 개요참조하세요.

이 항목에 표시된 코드 예제는 인쇄 작업 관리 및 프린터 기본 테넌트 샘플의 C# 버전을 기반으로 합니다. 이 샘플은 JavaScript 및 C++에서도 사용할 수 있습니다. C++는 COM에 직접 액세스할 수 있으므로 샘플의 C++ 버전에는 코드 라이브러리 프로젝트가 포함되지 않습니다. 샘플을 다운로드하여 최신 버전의 코드를 확인합니다.

인쇄 작업 관리

Windows 8.1에는 인쇄 작업을 관리하는 데 사용할 수 있는 v4 프린터 드라이버의 새로운 프린터 확장 인터페이스인 IPrinterQueue2, IPrinterQueueView, IPrinterQueueViewEvent, IPrintJob IPrintJobCollection이 도입되었습니다. 이러한 인터페이스를 사용하면 인쇄 작업을 모니터링하고 취소할 수 있습니다. 자세한 내용은 인쇄 작업 관리(v4 프린터 드라이버)를 참조하세요.

C# 및 JavaScript 앱은 COM API에서 직접 작동할 수 없습니다. C# 또는 JavaScript UWP 디바이스 앱을 작성하는 경우 프린터 확장 라이브러리를 사용하여 이 항목과 같이 이러한 인터페이스에 액세스합니다.

필수 조건

시작하기 전에 다음을 수행합니다.

  1. v4 인쇄 드라이버를 사용하여 프린터가 설치되어 있는지 확인합니다. 자세한 내용은 v4 인쇄 드라이버 개발을 참조 하세요.

  2. 개발 PC를 설정합니다. 도구 다운로드 및 개발자 계정 만들기에 대한 자세한 내용은 시작 정보를 참조하세요.

  3. 스토어와 앱을 연결합니다. 자세한 내용은 UWP 디바이스 앱 만들기를 참조하세요.

  4. 프린터를 앱과 연결하는 디바이스 메타데이터를 만듭니다. 자세한 내용은 디바이스 메타데이터 만들기를 참조하세요.

  5. 앱의 기본 페이지에 대한 UI를 빌드합니다. 모든 UWP 디바이스 앱은 시작에서 시작할 수 있으며 여기에서 전체 화면으로 표시됩니다. 시작 환경을 사용하여 디바이스의 특정 브랜딩 및 기능과 일치하는 방식으로 제품 또는 서비스를 강조 표시합니다. 사용할 수 있는 UI 컨트롤 유형에는 특별한 제한이 없습니다. 전체 화면 환경의 디자인을 시작하려면 Microsoft Store 디자인 원칙을 참조하세요.

  6. C# 또는 JavaScript를 사용하여 앱을 작성하는 경우 UWP 디바이스 앱 솔루션에 PrinterExtensionLibrary 프로젝트를 추가합니다. 인쇄 작업 관리 및 프린터 기본 테넌트 샘플에서 이 프로젝트를 찾을 수 있습니다.

C++는 COM에 직접 액세스할 수 있으므로 C++ 앱은 COM 기반 프린터 디바이스 컨텍스트를 사용하기 위해 별도의 라이브러리가 필요하지 않습니다.

1단계: 프린터 찾기

앱에서 인쇄 작업을 관리하려면 먼저 인쇄 작업이 있는 프린터를 찾아야 합니다. 이를 위해 인쇄 작업 관리 및 프린터 기본 테넌트 샘플에는 PrinterEnumeration.cs 파일에 이름이 지정된 PrinterEnumeration 편리한 클래스가 포함되어 있습니다. 이 클래스는 디바이스 메타데이터를 통해 앱과 연결된 모든 프린터를 찾고 각 프린터의 PrinterInfo 이름과 디바이스 ID를 포함하는 개체 목록을 반환합니다.

이 예제에서는 PrintJobManagement.xaml.cs 파일의 메서드를 보여줍니다EnumeratePrinters_Click. 샘플에서 클래스를 PrinterEnumeration 사용하여 연결된 프린터 목록을 가져오는 방법을 보여 줍니다.

private async void EnumeratePrinters_Click(object sender, RoutedEventArgs e)
{
    try
    {
        rootPage.NotifyUser("Enumerating printers. Please wait", NotifyType.StatusMessage);

        // Retrieve the running app's package family name, and enumerate associated printers.
        string currentPackageFamilyName = Windows.ApplicationModel.Package.Current.Id.FamilyName;

        // Enumerate associated printers.
        PrinterEnumeration pe = new PrinterEnumeration(currentPackageFamilyName);
        List<PrinterInfo> associatedPrinters = await pe.EnumeratePrintersAsync();

        // Update the data binding source on the combo box that displays the list of printers.
        PrinterComboBox.ItemsSource = associatedPrinters;
        if (associatedPrinters.Count > 0)
        {
            PrinterComboBox.SelectedIndex = 0;
            rootPage.NotifyUser(associatedPrinters.Count + " printers enumerated", NotifyType.StatusMessage);
        }
        else
        {
            rootPage.NotifyUser(DisplayStrings.NoPrintersEnumerated, NotifyType.ErrorMessage);
        }
    }
    catch (Exception exception)
    {
        rootPage.NotifyUser("Caught an exception: " + exception.Message, NotifyType.ErrorMessage);
    }
}

클래스 및 클래스에 PrinterEnumeration 대한 자세한 내용은 PrinterEnumeration.cs 파일을 참조 PrinterInfo 하세요.

2단계: 프린터 큐 가져오기

관리하려는 인쇄 작업이 있는 프린터를 확인한 후에는 인터페이스(PrinterExtensionLibrary 프로젝트의 PrinterExtensionTypes.cs 파일에 정의됨)를 기반으로 IPrinterQueueView 개체를 사용하여 인쇄 작업의 보기를 만듭니다. 인쇄 작업 관리 및 프린터 기본 테넌트 샘플에서 이 개체의 이름은 지정 currentPrinterQueueView 되며 프린터 선택이 변경 될 때마다 다시 만들어집니다.

Printer_SelectionChanged 메서드에서 샘플은 먼저 개체를 PrinterInfo 사용하여 명명 context된 프린터 확장 컨텍스트 개체를 만듭니다. 그런 다음 개체를 GetPrinterQueueView 만들기 위해 메서드 contextcurrentPrinterQueueView 사용합니다. 마지막으로 이벤트 처리기가 추가되어 '의 OnChanged 이벤트를 처리currentPrinterQueueView합니다.

이 예제에서는 PrintJobManagement.xaml.cs 파일의 메서드를 보여줍니다Printer_SelectionChanged. 을 기반으로 IPrinterQueueView프린터 큐 뷰 개체를 만드는 방법을 보여 있습니다.

private void Printer_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    try
    {
        // Remove the current printer queue view (if any) before displaying the new view.
        if (currentPrinterQueueView != null)
        {
            currentPrinterQueueView.OnChanged -= OnPrinterQueueViewChanged;
            currentPrinterQueueView = null;
        }

        // Retrieve a COM IPrinterExtensionContext object, using the static WinRT factory.
        // Then instantiate one "PrinterExtensionContext" object that allows operations on the COM object.
        PrinterInfo queue = (PrinterInfo)PrinterComboBox.SelectedItem;
        Object comContext = Windows.Devices.Printers.Extensions.PrintExtensionContext.FromDeviceId(queue.DeviceId);
        PrinterExtensionContext context = new PrinterExtensionContext(comContext);

        // Display the printer queue view.
        const int FirstPrintJobEnumerated = 0;
        const int LastPrintJobEnumerated = 10;

        currentPrinterQueueView = context.Queue.GetPrinterQueueView(FirstPrintJobEnumerated, LastPrintJobEnumerated);
        currentPrinterQueueView.OnChanged += OnPrinterQueueViewChanged;
    }
    catch (Exception exception)
    {
        rootPage.NotifyUser("Caught an exception: " + exception.Message, NotifyType.ErrorMessage);
    }
}

또한 인쇄 작업의 보기가 변경 될 때마다 이벤트 처리기 메서드를 호출 합니다 OnPrinterQueueViewChanged . 이 메서드는 IEnumerable 개체 컬렉션을 IPrintJob 사용하여 다시 바인딩 PrintJobListBox 합니다. 컬렉션은 PrinterExtensionTypes.cs 파일에 정의된 개체를 통해 PrinterQueueViewEventArgs 메서드에 전달됩니다.

이 예제에서는 PrintJobManagement.xaml.cs 파일의 메서드를 보여줍니다OnPrinterQueueViewChanged.

private async void OnPrinterQueueViewChanged(object sender, PrinterQueueViewEventArgs e)
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        // Update the data binding on the ListBox that displays print jobs.
        PrintJobListBox.ItemsSource = e.Collection;
        if (PrintJobListBox.Items.Count > 0)
        {
            // If there are print jobs in the current view, mark the first job as selected.
            PrintJobListBox.SelectedIndex = 0;
        }
    });
}

3단계: 인쇄 작업 상태 표시

PrintJobListBox 개체 컬렉션 IPrintJob 에 바인딩되므로 작업의 상태 표시하는 것은 매우 간단합니다. 선택한 인쇄 작업이 개체로 IPrintJob 캐스팅된 다음 해당 개체의 속성을 사용하여 TextBox를 PrintJobDetails 채웁니다.

인쇄 작업 관리 및 프린터 기본 테넌트 샘플에서는 다른 인쇄 작업을 선택할 때마다 인쇄 작업 상태 표시됩니다. 이 업데이트는 메서드에 의해 처리됩니다 PrintJob_SelectionChanged .

이 예제에서는 PrintJobManagement.xaml.cs 파일의 메서드를 보여줍니다PrintJob_SelectionChanged. 개체에 따라 IPrintJob 인쇄 작업의 상태 표시하는 방법을 보여줍니다.

private void PrintJob_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    try
    {
        // Display details of the selected print job.
        IPrintJob job = (IPrintJob)PrintJobListBox.SelectedItem;
        if (job != null)
        {
            PrintJobDetails.Text =
                "Details of print job: " + job.Name + "\r\n" +
                "Pages printed: " + job.PrintedPages + "/" + job.TotalPages + "\r\n" +
                "Submission time: " + job.SubmissionTime + "\r\n" +
                "Job status: " + DisplayablePrintJobStatus.ToString(job.Status);
        }
        else
        {
            PrintJobDetails.Text = "Please select a print job";
        }
    }
    catch (Exception exception)
    {
        rootPage.NotifyUser("Caught an exception: " + exception.Message, NotifyType.ErrorMessage);
    }
}

인쇄 작업 상태 설명을 PrintJob_SelectionChanged 표시하기 위해 메서드는 명명된 printJobStatusDisplayNames정적 사전을 사용하여 사용자에게 친숙한 텍스트 형식의 작업 상태 설명을 표시합니다.

이 예제에서는 PrintJobManagement.xaml.cs 파일의 클래스를 보여줍니다DisplayablePrintJobStatus. 이 클래스에는 .에서 사용하는 정적 멤버가 포함됩니다 PrintJob_SelectionChanged.

internal class DisplayablePrintJobStatus
{
    /// <summary>
    /// Converts the PrintJobStatus bit fields to a display string.
    /// </summary>
    internal static string ToString(PrintJobStatus printJobStatus)
    {
        StringBuilder statusString = new StringBuilder();

        // Iterate through each of the PrintJobStatus bits that are set and convert it to a display string.
        foreach (var printJobStatusDisplayName in printJobStatusDisplayNames)
        {
            if ((printJobStatusDisplayName.Key & printJobStatus) != 0)
            {
                statusString.Append(printJobStatusDisplayName.Value);
            }
        }

        int stringlen = statusString.Length;
        if (stringlen > 0)
        {
            // Trim the trailing comma from the string.
            return statusString.ToString(0, stringlen - 1);
        }
        else
        {
            // If no print job status field was set, display "Not available".
            return "Not available";
        }
    }

    /// <summary>
    /// Static constructor that initializes the display name for the PrintJobStatus field.
    /// </summary>
    static DisplayablePrintJobStatus()
    {
        printJobStatusDisplayNames = new Dictionary<PrintJobStatus, string>();

        printJobStatusDisplayNames.Add(PrintJobStatus.Paused, "Paused,");
        printJobStatusDisplayNames.Add(PrintJobStatus.Error, "Error,");
        printJobStatusDisplayNames.Add(PrintJobStatus.Deleting, "Deleting,");
        printJobStatusDisplayNames.Add(PrintJobStatus.Spooling, "Spooling,");
        printJobStatusDisplayNames.Add(PrintJobStatus.Printing, "Printing,");
        printJobStatusDisplayNames.Add(PrintJobStatus.Offline, "Offline,");
        printJobStatusDisplayNames.Add(PrintJobStatus.PaperOut, "Out of paper,");
        printJobStatusDisplayNames.Add(PrintJobStatus.Printed, "Printed,");
        printJobStatusDisplayNames.Add(PrintJobStatus.Deleted, "Deleted,");
        printJobStatusDisplayNames.Add(PrintJobStatus.BlockedDeviceQueue, "Blocked device queue,");
        printJobStatusDisplayNames.Add(PrintJobStatus.UserIntervention, "User intervention required,");
        printJobStatusDisplayNames.Add(PrintJobStatus.Restarted, "Restarted,");
        printJobStatusDisplayNames.Add(PrintJobStatus.Complete, "Complete,");
        printJobStatusDisplayNames.Add(PrintJobStatus.Retained, "Retained,");
    }
    
    /// <summary>
    /// Private constructor to prevent default instantiation.
    /// </summary>
    private DisplayablePrintJobStatus() { }

    /// <summary>
    /// Contains the mapping between PrintJobStatus fields and display strings.
    /// </summary>
    private static Dictionary<PrintJobStatus, string> printJobStatusDisplayNames;
}

4단계: 인쇄 작업 취소

인쇄 작업 상태 표시하는 것과 마찬가지로 개체가 있는 경우 IPrintJob 인쇄 작업을 취소하는 것은 매우 간단합니다. 클래스는 IPrintJob 해당 인쇄 작업의 취소를 시작하는 메서드를 제공합니다 RequestCancel . 이는 샘플의 CancelPrintJob_Click 메서드에서 설명합니다.

이 예제에서는 PrintJobManagement.xaml.cs 파일의 메서드를 보여줍니다CancelPrintJob_Click.

private void CancelPrintJob_Click(object sender, RoutedEventArgs e)
{
    try
    {
        IPrintJob job = (IPrintJob)PrintJobListBox.SelectedItem;
        job.RequestCancel();
    }
    catch (Exception exception)
    {
        rootPage.NotifyUser("Caught an exception: " + exception.Message, NotifyType.ErrorMessage);
    }
}

테스팅

UWP 디바이스 앱을 테스트하려면 먼저 디바이스 메타데이터를 사용하여 프린터에 연결해야 합니다.

디바이스 앱 정보를 추가하려면 프린터에 대한 디바이스 메타데이터 패키지의 복사본이 필요합니다. 디바이스 메타데이터가 없는 경우 UWP 디바이스 앱에 대한 디바이스 메타데이터 만들기 항목에 설명된 대로 디바이스 메타데이터 작성 마법사를 사용하여 빌드할 수 있습니다.

디바이스 메타데이터 작성 마법사를 사용하려면 이 항목의 단계를 완료하기 전에 Microsoft Visual Studio Professional, Microsoft Visual Studio Ultimate 또는 Windows 8.1용 독립 실행형 SDK를 설치해야 합니다. Windows용 Microsoft Visual Studio Express를 설치하면 마법사를 포함하지 않는 SDK 버전이 설치됩니다.

다음 단계에서는 앱을 빌드하고 디바이스 메타데이터를 설치합니다.

  1. 테스트 서명을 사용하도록 설정합니다.

    1. DeviceMetadataWizard.exe 두 번 클릭하여 %ProgramFiles(x86)%\Windows Kits\8.1\bin\x86에서 디바이스 메타데이터 제작 마법사시작합니다.

    2. 도구 메뉴에서 테스트 서명 사용을 선택합니다.

  2. 컴퓨터를 다시 부팅

  3. 솔루션(.sln) 파일을 열어 솔루션을 빌드합니다. F7 키를 누르거나 샘플이 로드된 후 상단 메뉴에서 빌드> 솔루션으로 이동합니다.

  4. 프린터 연결을 끊고 제거합니다. 이 단계는 다음에 디바이스가 검색될 때 Windows에서 업데이트된 디바이스 메타데이터를 읽도록 하는 데 필요합니다.

  5. 디바이스 메타데이터를 편집하고 저장합니다. 디바이스 앱을 디바이스에 연결하려면 디바이스 앱을 디바이스와 연결해야 합니다.

    디바이스 메타데이터를 아직 만들지 않은 경우 UWP 디바이스 앱에 대한 디바이스 메타데이터 만들기를 참조하세요.

    1. 디바이스 메타데이터 작성 마법사가 아직 열려 있지 않으면 DeviceMetadataWizard.exe 두 번 클릭하여 %ProgramFiles(x86)%\Windows Kits\8.1\bin\x86에서 시작합니다.

    2. 디바이스 메타데이터 편집을 클릭합니다. 이렇게 하면 기존 디바이스 메타데이터 패키지를 편집할 수 있습니다.

    3. 열기 대화 상자에서 UWP 디바이스 앱과 연결된 디바이스 메타데이터 패키지를 찾습니다. (devicemetadata-ms 파일 확장명입니다.)

    4. UWP 디바이스 앱 정보 지정 페이지의 UWP 디바이스 앱 상자에 Microsoft Store 앱 정보를 입력합니다. UWP 앱 매니페스트 파일 가져오기를 클릭하여 패키지 이름, 게시자 이름UWP 앱 ID를 자동으로 입력합니다.

    5. 앱이 프린터 알림을 등록하는 경우 알림 처리기 상자를 입력 합니다 . 이벤트 ID에서 인쇄 이벤트 처리기의 이름을 입력합니다. 이벤트 자산에서 해당 코드가 있는 파일의 이름을 입력합니다.

    6. 완료되면 마침 페이지에 도착할 때까지 다음클릭합니다.

    7. 디바이스 메타데이터 패키지 검토 페이지에서 모든 설정이 올바른지 확인하고 로컬 컴퓨터 검사 상자의 메타데이터 저장소에 디바이스 메타데이터 패키지 복사를 선택합니다. 그런 다음 Save를 클릭합니다.

  6. 디바이스가 연결될 때 Windows에서 업데이트된 디바이스 메타데이터를 읽도록 프린터를 다시 연결합니다.

작업 관리(v4 프린터 드라이버)

v4 인쇄 드라이버 개발

양방향 통신

UWP 앱 시작

UWP 디바이스 앱 만들기(단계별 가이드)

UWP 디바이스 앱에 대한 디바이스 메타데이터 만들기(단계별 가이드)