印刷ワークフローのカスタマイズCustomize the print workflow

概要Overview

開発者は、印刷ワークフロー アプリを使用して印刷ワークフローのエクスペリエンスをカスタマイズできます。Developers can customize the printing workflow experience through the use of a print workflow app. 印刷ワークフロー アプリは、Microsoft Store デバイス アプリ (MSDA) の機能を拡張する UWP アプリです。このアプリを使用すると、MSDA の詳細を習得する前に、MSDA の概要を理解することができます。Print workflow apps are UWP apps that expand on the functionality of Microsoft Store devices apps (WSDAs), so it will be helpful to have some familiarity with WSDAs before going further.

MSDA の場合と同様に、ソース アプリケーションのユーザーが印刷の実行と印刷ダイアログのナビゲーションをする場合、システムによって、ワークフロー アプリがそのプリンターに関連付けられているかどうかが確認されます。Just as in the case of WSDAs, when the user of a source application elects to print something and navigates through the print dialog, the system checks whether a workflow app is associated with that printer. 関連付けられている場合は、印刷ワークフロー アプリが起動します (主にバックグラウンド タスクとして起動されます。以下で詳しく説明します)。If it is, the print workflow app launches (primarily as a background task; more on this below). ワークフロー アプリは、印刷チケット (現在の印刷タスク向けにプリンター デバイスの設定を構成する XML ドキュメント) と印刷される実際の XPS コンテンツの両方を変更することができます。A workflow app is able to alter both the print ticket (the XML document that configures the printer device settings for the current print task) and the actual XPS content to be printed. 必要に応じて、印刷操作を行っているときに UI を起動することにより、この機能をユーザーに公開することもできます。It can optionally expose this functionality to the user by launching a UI midway through the process. 印刷ワークフロー アプリの処理が終了すると、印刷コンテンツと印刷チケットがドライバーに渡されます。After doing its work, it passes the print content and print ticket on to the driver.

バックグラウンド コンポーネントとフォアグラウンド コンポーネントが関連しているため、また他のアプリと機能的に組み合わされるため、印刷ワークフロー アプリは、他の種類の UWP アプリと比べると実装が複雑になる可能性があります。Because it involves background and foreground components, and because it is functionally coupled with other app(s), a print workflow app can be more complicated to implement than other categories of UWP apps. このガイドをお読みになるときは、ワークフロー アプリのサンプルについて調べることをお勧めします。これにより、さまざまな機能の実装方法ついて詳しく理解することができます。It is recommended that you inspect the Workflow app sample while reading this guide to better understand how the different features can be implemented. 説明を簡単にするために、このガイドでは一部の機能 (さまざまなエラー チェックや UI の管理など) が省略されています。Some features, such as various error checks and UI management, are absent from this guide for the sake of simplicity.

概要Getting started

ワークフロー アプリでは、適切なタイミングで起動できるように、印刷システムへのエントリ ポイントを示す必要があります。The workflow app must indicate its entry point to the print system so that it can be launched at the appropriate time. これを行うには、UWP プロジェクトの package.appxmanifest ファイルの Application/Extensions 要素にある以下の宣言を挿入します。This is done by inserting the following declaration in the Application/Extensions element of the UWP project's package.appxmanifest file.

<uap:Extension Category="windows.printWorkflowBackgroundTask"  
    EntryPoint="WFBackgroundTasks.WfBackgroundTask" />

重要

印刷のカスタマイズでユーザー入力を必要としないシナリオはたくさんあります。There are many scenarios in which the print customization does not require user input. このため、既定では、印刷ワークフロー アプリはバックグラウンド タスクとして実行されます。For this reason, Print workflow apps run as background tasks by default.

ワークフロー アプリを、印刷ジョブを開始したソース アプリケーションと関連付ける場合 (この手順については後のセクションをご覧ください)、印刷システムによってマニフェスト ファイルが検査され、バックグラウンド タスクのエントリ ポイントが調べられます。If a workflow app is associated with the source application that started the print job (see later section for instructions on this), the print system examines its manifest files for a background task entry point.

印刷チケットに対するバックグラウンド処理の実行Do background work on the print ticket

印刷システムがワークフロー アプリを使用して実行する最初の処理は、バックグラウンド タスク (この場合は WFBackgroundTasks 名前空間の WfBackgroundTask クラス) のアクティブ化です。The first thing the print system does with the workflow app is activate its background task (In this case, the WfBackgroundTask class in the WFBackgroundTasks namespace). バックグラウンド タスクの Run メソッドでは、タスクのトリガーの詳細を PrintWorkflowTriggerDetails インスタンスとしてキャストする必要があります。In the background task's Run method, you should cast the task's trigger details as a PrintWorkflowTriggerDetails instance. これにより、印刷ワークフローのバックグラウンド タスク向けの特別な機能が利用できるようになります。This will provide the special functionality for a print workflow background task. また、PrintWorkFlowBackgroundSession のインスタンスである PrintWorkflowSession プロパティが公開されます。It exposes the PrintWorkflowSession property, which is an instance of PrintWorkFlowBackgroundSession. 印刷ワークフロー セッションのクラス (バックグラウンドとフォアグラウンドの両方に関するクラス) によって、印刷ワークフロー アプリの一連の手順が制御されます。Print workflow session classes - both the background and foreground varieties - will control the sequential steps of the print workflow app.

次に、このセッションのクラスで発生する 2 つのイベント用のハンドラー メソッドを登録します。Then register handler methods for the two events that this session class will raise. これらのメソッドの定義は、後で行います。You will define these methods later on.

public void Run(IBackgroundTaskInstance taskInstance) {
    // Take out a deferral here and complete once all the callbacks are done
    runDeferral = taskInstance.GetDeferral();

    // Associate a cancellation handler with the background task.
    taskInstance.Canceled += new BackgroundTaskCanceledEventHandler(OnCanceled);

    // cast the task's trigger details as PrintWorkflowTriggerDetails
    PrintWorkflowTriggerDetails workflowTriggerDetails = taskInstance.TriggerDetails as PrintWorkflowTriggerDetails;

    // Get the session manager, which is unique to this print job
    PrintWorkflowBackgroundSession sessionManager = workflowTriggerDetails.PrintWorkflowSession;

    // add the event handler callback routines
    sessionManager.SetupRequested += OnSetupRequested;
    sessionManager.Submitted += OnXpsOMPrintSubmitted;

    // Allow the event source to start
    // This call blocks until all of the workflow callbacks complete
    sessionManager.Start();
}

Start メソッドが呼び出されると、まずセッション マネージャーで SetupRequested イベントが発生します。When the Start method is called, the session manager will raise the SetupRequested event first. このイベントによって、印刷タスクと印刷チケットに関する一般的な情報が公開されます。This event exposes general information about the print task, as well as the print ticket. この段階では、印刷チケットをバックグラウンドで編集できます。At this stage, the print ticket can be edited in the background.

private void OnSetupRequested(PrintWorkflowBackgroundSession sessionManager, PrintWorkflowBackgroundSetupRequestedEventArgs printTaskSetupArgs) {
    // Take out a deferral here and complete once all the callbacks are done
    Deferral setupRequestedDeferral = printTaskSetupArgs.GetDeferral();

    // Get general information about the source application, print job title, and session ID
    string sourceApplicationName = printTaskSetupArgs.Configuration.SourceAppDisplayName;
    string jobTitle = printTaskSetupArgs.Configuration.JobTitle;
    string sessionId = printTaskSetupArgs.Configuration.SessionId;

    // edit the print ticket
    WorkflowPrintTicket printTicket = printTaskSetupArgs.GetUserPrintTicketAsync();

    // ...

重要な点は、SetupRequested の処理で、アプリがフォアグラウンドコンポーネントを起動するかどうかを決定することです。Importantly, it is in the handling of the SetupRequested that the app will determine whether to launch a foreground component. これは、ローカル記憶域に以前保存した設定、または印刷チケットの編集中に発生したイベントによって決まります。あるいは、特定のアプリの静的な設定がこの決定に影響する場合もあります。This could depend on a setting that was previously saved to local storage, or an event that occurred during the editing of the print ticket, or it may be a static setting of your particular app.

    // ...
    
    if (UIrequested) {
        printTaskSetupArgs.SetRequiresUI();

        // Any data that is to be passed to the foreground task must be stored the app's local storage.
        // It should be prefixed with the sourceApplicationName string and the SessionId string, so that
        // it can be identified as pertaining to this workflow app session.
    }

    // Complete the deferral taken out at the start of OnSetupRequested
    setupRequestedDeferral.Complete();
}

印刷ジョブに対するフォアグラウンド処理の実行 (オプション)Do foreground work on the print job (optional)

SetRequiresUI メソッドが呼び出されると、印刷システムによってマニフェスト ファイルが検査され、フォアグラウンド アプリケーションへのエントリ ポイントが調べられます。If the SetRequiresUI method was called, then the print system will examine the manifest file for the entry point to the foreground application. package.appxmanifest ファイルの Application/Extensions 要素には、以下の行が含まれている必要があります。The Application/Extensions element of your package.appxmanifest file must have the following lines. EntryPoint の値は、フォアグラウンド アプリの名前に変更してください。Replace the value of EntryPoint with name of the foreground app.

<uap:Extension Category="windows.printWorkflowForegroundTask"  
    EntryPoint="MyWorkFlowForegroundApp.App" /> 

次に、印刷システムによって、指定されたアプリのエントリ ポイントで OnActivated メソッドが呼び出されます。Next, the print system calls the OnActivated method for the given app entry point. App.xaml.cs ファイルの OnActivated メソッドでは、ワークフロー アプリはアクティブ化の種類を調べ、ワークフローのアクティブ化であることを確認する必要があります。In the OnActivated method of its App.xaml.cs file, the workflow app should check the activation kind to verify that it is a workflow activation. ワークフローのアクティブ化である場合、ワークフロー アプリではアクティブ化引数を PrintWorkflowUIActivatedEventArgs オブジェクトにキャストできます。このオブジェクトでは、PrintWorkflowForegroundSession オブジェクトがプロパティとして公開されます。If so, the workflow app can cast the activation arguments to a PrintWorkflowUIActivatedEventArgs object, which exposes a PrintWorkflowForegroundSession object as a property. このオブジェクトは、前のセクションのバックグラウンドに対応するもので、印刷システムで発生するイベントを含んでいます。これらのイベントには、ハンドラーを割り当てることができますThis object, like its background counterpart in the previous section, contains events that are raised by the print system, and you can assign handlers to these. この場合、イベント処理機能は WorkflowPage という個別のクラスに実装されます。In this case, the event-handling functionality will be implemented in a separate class called WorkflowPage.

まず、App.xaml.cs ファイルの例を次に示します。First, in the App.xaml.cs file:

protected override void OnActivated(IActivatedEventArgs args){

    if (args.Kind == ActivationKind.PrintWorkflowForegroundTask) {

        // the app should instantiate a new UI view so that it can properly handle the case when 
        // several print jobs are active at the same time.
        Frame rootFrame = new Frame();
        if (null == Window.Current.Content)
        {
            rootFrame.Navigate(typeof(WorkflowPage));
            Window.Current.Content = rootFrame;
        }

        // Get the main page
        WorkflowPage workflowPage = (WorkflowPage)rootFrame.Content;

        // Make sure the page knows it's handling a foreground task activation
        workflowPage.LaunchType = WorkflowPage.WorkflowPageLaunchType.ForegroundTask;

        // Get the activation arguments
        PrintWorkflowUIActivatedEventArgs printTaskUIEventArgs = args as PrintWorkflowUIActivatedEventArgs;

        // Get the session manager
        PrintWorkflowForegroundSession taskSessionManager = printTaskUIEventArgs.PrintWorkflowSession;

        // Add the callback handlers - these methods are in the workflowPage class
        taskSessionManager.SetupRequested += workflowPage.OnSetupRequested;
        taskSessionManager.XpsDataAvailable += workflowPage.OnXpsDataAvailable;

        // start raising the print workflow events
        taskSessionManager.Start();
    }
}

UI がイベント ハンドラーをアタッチし、OnActivated メソッドが終了すると、UI による処理ができるように、印刷システムでは SetupRequested イベントが発生します。Once the UI has attached event handlers and the OnActivated method has exited, the print system will fire the SetupRequested event for the UI to handle. このイベントでは、バックグラウンド タスクのセットアップ イベントで提供されるものと同じデータが提供されます。このデータには、印刷ジョブの情報や印刷チケットのドキュメントが含まれますが、追加の UI の起動を要求する機能は含まれていません。This event provides the same data that the background task setup event provided, including the print job info and print ticket document, but without the ability to request the launch of additional UI. WorkflowPage.xaml.cs ファイルの例を次に示します。In the WorkflowPage.xaml.cs file:

internal void OnSetupRequested(PrintWorkflowForegroundSession sessionManager, PrintWorkflowForegroundSetupRequestedEventArgs printTaskSetupArgs) {
    // If anything asynchronous is going to be done, you need to take out a deferral here,
    // since otherwise the next callback happens once this one exits, which may be premature
    Deferral setupRequestedDeferral = printTaskSetupArgs.GetDeferral();

    // Get information about the source application, print job title, and session ID
    string sourceApplicationName = printTaskSetupArgs.Configuration.SourceAppDisplayName;
    string jobTitle = printTaskSetupArgs.Configuration.JobTitle;
    string sessionId = printTaskSetupArgs.Configuration.SessionId;
    // the following string should be used when storing data that pertains to this workflow session
    // (such as user input data that is meant to change the print content later on)
    string localStorageVariablePrefix = string.Format("{0}::{1}::", sourceApplicationName, sessionID);
    
    try
    {
        // receive and store user input
        // ...
    }
    catch (Exception ex)
    {
        string errorMessage = ex.Message;
        Debug.WriteLine(errorMessage);
    }
    finally
    {
        // Complete the deferral taken out at the start of OnSetupRequested
        setupRequestedDeferral.Complete();
    }
}

次に、印刷システムによって、UI 用の XpsDataAvailable イベントが発生します。Next, the print system will raise the XpsDataAvailable event for the UI. このイベントのハンドラーでは、ワークフロー アプリはセットアップ イベントで利用できるすべてのデータにアクセスできます。また、追加の XPS データを、未処理のバイトのストリームまたはオブジェクト モデルとして直接読み取ることもできます。In the handler for this event, the workflow app can access all of the data available to the setup event and can additionally read the XPS data directly, either as a stream of raw bytes or as an object model. XPS データへのアクセスによって、UI では印刷プレビュー サービスを提供し、ワークフロー アプリがデータに対して実行する処理についての追加情報をユーザーに提供することができます。Access to the XPS data allows the UI to provide print preview services and to provide additional information to the user about the operations that the workflow app will execute on the data.

このイベント ハンドラーの一環として、ワークフロー アプリでは、ユーザーとのやり取りを継続する場合に遅延オブジェクトを取得する必要があります。As part of this event handler, the workflow app must acquire a deferral object if it will continue to interact with the user. 遅延を使用しないと、印刷システムでは、XpsDataAvailable イベント ハンドラーが終了したとき、またはこのハンドラーで非同期メソッドが呼び出されたときに UI タスクが完了したと見なされます。Without a deferral, the print system will consider the UI task complete when the XpsDataAvailable event handler exits or when it calls an async method. アプリがユーザーと UI とのやり取りから必要な情報をすべて収集したときに、アプリでは遅延を終了し、印刷システムが次の処理に進めるようにする必要があります。When the app has gathered all required information from the user's interaction with the UI, it should complete the deferral so that the print system can then advance.

internal async void OnXpsDataAvailable(PrintWorkflowForegroundSession sessionManager, PrintWorkflowXpsDataAvailableEventArgs printTaskXpsAvailableEventArgs)
{
    // Take out a deferral
    Deferral xpsDataAvailableDeferral = printTaskXpsAvailableEventArgs.GetDeferral();

    SpoolStreamContent xpsStream = printTaskXpsAvailableEventArgs.Operation.XpsContent.GetSourceSpoolDataAsStreamContent(); 
 
    IInputStream inputStream = xpsStream.GetInputSpoolStream(); 
 
    using (var inputReader = new Windows.Storage.Streams.DataReader(inputStream)) 
    { 
        // Read the XPS data from input stream 
        byte[] xpsData = new byte[inputReader.UnconsumedBufferLength]; 
        while (inputReader.UnconsumedBufferLength > 0) 
        { 
            inputReader.ReadBytes(xpsData); 
            // Do something with the XPS data, e.g. preview 
            // ...                  
        } 
    } 

    // Complete the deferral taken out at the start of this method
    xpsDataAvailableDeferral.Complete();
}

また、イベント引数によって公開される PrintWorkflowSubmittedOperation インスタンスでは、印刷ジョブを取り消したり、印刷ジョブは成功したが出力の印刷ジョブが必要ないことを指定したりするためのオプションが提供されます。Additionally, the PrintWorkflowSubmittedOperation instance exposed by the event args provides the option to cancel the print job or to indicate that the job is successful but that no output print job will be needed. これは、PrintWorkflowSubmittedStatus 値を使用して Complete メソッドを呼び出すことで実行されます。This is done by calling the Complete method with a PrintWorkflowSubmittedStatus value.

注意

ワークフロー アプリで印刷ジョブを取り消す場合は、ジョブが取り消された理由を示すトースト通知を提供することを強くお勧めします。If the workflow app cancels the print job, it is highly recommended that it provide a toast notification indicating why the job was cancelled.

印刷コンテンツに対する最終的なバックグラウンド処理の実行Do final background work on the print content

UI で PrintTaskXpsDataAvailable イベントの遅延が完了した場合 (または UI の手順が省略された場合)、印刷システムではバックグラウンド タスク用の Submitted イベントが発生します。Once the UI has completed the deferral in the PrintTaskXpsDataAvailable event (or if the UI step was bypassed), the print system will fire the Submitted event for the background task. このイベントのハンドラーでは、ワークフロー アプリは XpsDataAvailable イベントで提供されるものと同じすべてのデータにアクセスできます。In the handler for this event, the workflow app can get access to all of the same data provided by the XpsDataAvailable event. ただし、これまでのイベントとは異なり、SubmittedPrintWorkflowTarget インスタンスを使用して、最終的な印刷ジョブのコンテンツに対する書き込みアクセスを提供します。However, unlike any of the previous events, Submitted also provides write access to the final print job content through a PrintWorkflowTarget instance.

最終的な印刷で必要となるデータをスプールする場合に使用されるオブジェクトは、ソース データが未処理のバイトのストリームとしてアクセスされるのか、XPS オブジェクト モデルとしてアクセスされるのかによって異なります。The object that is used to spool the data for final printing depends on whether the source data is accessed as a raw byte stream or as the XPS object model. ワークフロー アプリがバイト ストリームを介してソース データにアクセスするときは、最終的なジョブ データを書き込むために、出力のバイト ストリームが提供されます。When the workflow app accesses the source data through a byte stream, an output byte stream is provided to write the final job data to. ワークフロー アプリがオブジェクト モデルを介してソース データにアクセスするときは、オブジェクトを出力ジョブに書き込むために、ドキュメント ライターが提供されます。When the workflow app accesses the source data through the object model, a document writer is provided to write objects to the output job. どちらの場合も、ワークフロー アプリでは、すべてのソース データを読み取り、必要なデータを変更し、変更されたデータを出力ターゲットに書き込む必要があります。In either case, the workflow app should read all of the source data, modify any data required, and write the modified data to the output target.

バックグラウンド タスクでデータの書き込みが完了したら、対応する PrintWorkflowSubmittedOperation オブジェクトで Complete を呼び出します。When the background task finishes writing the data, it should call Complete on the corresponding PrintWorkflowSubmittedOperation object. ワークフロー アプリでこの手順が完了し、Submitted イベント ハンドラーが終了すると、ワークフロー セッションが閉じられ、ユーザーは、標準的な印刷ダイアログで最終的な印刷ジョブの状態を監視できます。Once the workflow app completes this step and the Submitted event handler exits, the workflow session is closed and the user can monitor the status of the final print job through the standard print dialogs.

最後の手順Final steps

印刷ワークフロー アプリをプリンターに登録するRegister the print workflow app to the printer

ワークフロー アプリは、MSDA の場合と同じ種類のメタデータ ファイル送信を使用するプリンターに関連付けられます。Your workflow app is associated with a printer using the same type of metadata file submission as for WSDAs. 実際には、1 つの UWP アプリケーションが、ワークフロー アプリと、印刷タスクの設定機能を提供する MSDA の両方として機能することができます。In fact, a single UWP application can act as both a workflow app and a WSDA that provides print task settings functionality. 関連する「MSDA steps for creating the metadata association」(メタデータの関連付けを作成するための MSDA の手順) に従ってください。Follow the corresponding WSDA steps for creating the metadata association.

相違点は、MSDA はユーザーに対して自動的にアクティブ化されますが (関連付けられているデバイスでユーザーが印刷を実行すると、アプリは常に起動されます)、ワークフロー アプリは自動的にはアクティブ化されないことです。The difference is that while WSDAs are automatically activated for the user (the app will always launch when that user prints on the associated device), workflow apps are not. これらのアプリに対しては、それぞれ別のポリシーを設定する必要があります。They have a separate policy that must be set.

ワークフロー アプリのポリシーの設定Set the workflow app's policy

ワークフロー アプリのポリシーは、ワークフロー アプリを実行するデバイス上で PowerShell コマンドによって設定されます。The workflow app policy is set by Powershell commands on the device that is to run the workflow app. Set-Printer、Add-Printer (既存のポート)、Add-Printer (新しい WSD ポート) の各コマンドを、ワークフロー ポリシーの設定を許可するように変更します。The Set-Printer, Add-Printer (existing port) and Add-Printer (new WSD port) commands will be modified to allow Workflow policies to be set.

  • Disabled :アプリのワークフローをアクティブにできません。Disabled: Workflow apps will not be activated.
  • Uninitialized :ワークフロー DCA がシステムにインストールされている場合、アプリのワークフローをアクティブ化されます。Uninitialized: Workflow apps will be activated if the Workflow DCA is installed in the system. アプリがインストールされていない場合は、印刷が引き続き実行されます。If the app is not installed, printing will still proceed.
  • Enabled :ワークフロー DCA がシステムにインストールされている場合、ワークフローのコントラクトをアクティブ化されます。Enabled: Workflow contract will be activated if the Workflow DCA is installed in the system. アプリがインストールされていない場合は、印刷は失敗します。If the app is not installed, printing will fail.

次のコマンドは、指定されたプリンターでワークフロー アプリを必須のアプリにします。The following command makes the workflow app required on the specified printer.

Set-Printer –Name "Microsoft XPS Document Writer" -WorkflowPolicy On

ローカル ユーザーは、このポリシーをローカル プリンタで実行することができます。企業での実装を目的とする場合、プリンターの管理者は、このポリシーをプリント サーバーで実行することができます。A local user can run this policy on a local printer, or, for enterprise implementation, the printer administrator can run this policy on the Print Server. 実行後、ポリシーはすべてのクライアント接続に対して同期されます。The policy will then be synchronized to all client connections. プリンターの管理者は、新しいプリンターを追加するたびにこのポリシーを使用できます。The printer admin can use this policy whenever a new printer is added.

関連項目See also

アプリのサンプルのワークフローWorkflow app sample

Windows.Graphics.Printing.Workflow 名前空間Windows.Graphics.Printing.Workflow namespace