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 プリンター ドライバーに新しいプリンター拡張機能インターフェイス (IPrinterQueue2IPrinterQueueViewIPrinterQueueViewEventIPrintJobIPrintJobCollection) が導入されています。 これらのインターフェイスにより、印刷ジョブの監視と取り消しが可能になります。 詳細については、「印刷ジョブの管理 (v4 プリンター ドライバー)」を参照してください。

C# アプリと JavaScript アプリでは、COM API を直接操作できません。 C# または JavaScript の UWP デバイス アプリを作成する場合は、(このトピックに示されているように) プリンター拡張機能ライブラリを使用してこれらのインターフェイスにアクセスします。

前提条件

開始する前に、以下の操作を行います。

  1. v4 プリンター ドライバーを使用してプリンターがインストールされていることを確認します。 詳しくは、「v4 プリンター ドライバーの開発」をご覧ください。

  2. 開発マシンを設定します。 ツールのダウンロードと開発者アカウントの作成については、「概要」を参照してください。

  3. ストアにアプリを関連付けます。 詳細については、「UWP デバイス アプリを作成する」を参照してください。

  4. プリンターをアプリに関連付けるプリンターのデバイス メタデータを作成します。 詳細については、「デバイス メタデータを作成する」を参照してください。

  5. アプリのメイン ページの UI を構築します。 すべての UWP デバイス アプリは [開始] から起動でき、全画面表示で表示されます。 開始エクスペリエンスを使用すると、デバイスの固有のブランドと機能に一致する方法で製品またはサービスを強調できます。 使用できる UI コントロールの種類に特別な制限はありません。 全画面表示エクスペリエンスの設計を開始するには、Microsoft Store 設計原則を参照してください。

  6. C# または JavaScript を使用してアプリを作成する場合は、PrinterExtensionLibrary プロジェクトを UWP デバイス アプリ ソリューションに追加します。 このプロジェクトは、印刷ジョブの管理とプリンター メンテナンスのサンプルにあります。

C++ は COM に直接アクセスできるため、C++ アプリには、COM ベースのプリンター デバイス コンテキストを操作するための別のライブラリは必要ありません。

手順 1: プリンターを検索する

アプリで印刷ジョブを管理する前に、まず印刷ジョブを持つプリンターを見つける必要があります。 これを行うために、印刷ジョブの管理とプリンター メンテナンスのサンプルには、(PrinterEnumerationPrinterEnumeration.cs ファイル内に) という名前の便利なクラスが含まれています。 このクラスは、デバイス メタデータを使用してアプリに関連付けられているすべてのプリンターを見つけて、各プリンターの名前とデバイス ID を含む PrinterInfo オブジェクトの一覧を返します。

この例は、EnumeratePrinters_ClickPrintJobManagement.xaml.cs ファイル内の メソッドを示します。 このサンプルが 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 クラスと PrinterInfo クラスの詳細については、PrinterEnumeration.cs ファイルを参照してください。

手順 2: プリンター キューを取得する

管理する印刷ジョブを持つプリンターを特定したら、 インターフェイス (PrinterExtensionLibraryIPrinterQueueView プロジェクトの PrinterExtensionTypes.cs ファイルで定義) に基づくオブジェクトを使用して、印刷ジョブのビューを作成します。 印刷ジョブの管理とプリンター メンテナンスのサンプルでは、このオブジェクトは currentPrinterQueueView という名前が付けられ、プリンターの選択が変更されるたびに再作成されます。

Printer_SelectionChanged メソッドでは、サンプルは最初に PrinterInfo オブジェクトを使用して、context という名前のプリンター拡張機能コンテキスト オブジェクトを作成します。 次に、GetPrinterQueueViewcontext メソッドを使用して currentPrinterQueueView オブジェクトを作成します。 最後に、currentPrinterQueueViewOnChanged イベントを処理するイベント ハンドラーが追加されます。

この例は、Printer_SelectionChangedPrintJobManagement.xaml.cs ファイル内の メソッドを示します。 これは、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 メソッドを呼び出します。 このメソッドにより、PrintJobListBoxIPrintJob オブジェクトの IEnumerable コレクションに再バインドされます。 コレクションは、PrinterQueueViewEventArgsPrinterExtensionTypes.cs ファイルで定義されている オブジェクトを介してメソッドに渡されます。

この例は、OnPrinterQueueViewChangedPrintJobManagement.xaml.cs ファイル内の メソッドを示します。

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: 印刷ジョブの状態を表示する

PrintJobListBoxIPrintJob オブジェクトのコレクションにバインドされているため、ジョブの状態の表示はかなり簡単です。 選択した印刷ジョブが IPrintJob オブジェクトとしてキャストされ、そのオブジェクトのプロパティを使用して PrintJobDetails TextBox を埋めます。

印刷ジョブの管理とプリンター メンテナンスのサンプルでは、異なる印刷ジョブが選択されるたびに印刷ジョブの状態が表示されます。 この更新は、PrintJob_SelectionChanged メソッドで管理されます。

この例は、PrintJob_SelectionChangedPrintJobManagement.xaml.cs ファイル内の メソッドを示します。 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 という名前の付いた静的ディクショナリを使用して、わかりやすいテキスト形式でジョブの状態の説明を表示できるようにします。

この例は、DisplayablePrintJobStatusPrintJobManagement.xaml.cs ファイル内の クラスを示します。 このクラスには、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 メソッドに示されています。

この例は、CancelPrintJob_ClickPrintJobManagement.xaml.cs ファイル内の メソッドを示します。

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、またはスタンドアロン SDK for Windows 8.1 をインストールする必要があります。 Microsoft Visual Studio Express for Windows をインストールすると、ウィザードを含まないバージョンの SDK がインストールされます。

次の手順に沿ってアプリを作成し、デバイス メタデータをインストールします。

  1. テスト署名を有効にします。

    1. DeviceMetadataWizard.exe をダブルクリックして、%ProgramFiles(x86)%\Windows Kits\8.1\bin\x86 からデバイス メタデータ作成ウィザードを開始します。

    2. [ツール] メニューの [テスト署名を有効にする] を選択します。

  2. コンピューターを再起動します

  3. ソリューション (.sln) ファイルを開いてソリューションを構築します。 サンプルが読み込まれた後、F7 キーを押すか、上部のメニューから [Build] -> [ソリューションの構築] に移動します。

  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. [デバイス メタデータ パッケージの確認] ページで、すべての設定が正しいことを確認し、[ローカル コンピューターのメタデータ ストアにデバイス メタデータ パッケージをコピーする] チェック ボックスを選択します。 [保存] をクリックします。

  6. デバイスが接続されている場合は、プリンターを再接続して、Windows が更新されたデバイス メタデータを読み取れるようにします。

ジョブ管理 (v4 プリンター ドライバー)

v4 印刷ドライバーの開発

双方向通信

UWP アプリの概要

UWP デバイス アプリを作成する (ステップ バイ ステップ ガイド)

UWP デバイス アプリのデバイス メタデータを作成する (ステップ バイ ステップ ガイド)