Partager via


Personnaliser le workflow d’impression

Créez des expériences de flux de travail d’impression personnalisées à l’aide d’une application de flux de travail d’impression.

Vue d’ensemble

Les applications de flux de travail d’impression sont des applications UWP qui s’étendent sur les fonctionnalités des applications d’appareils du Microsoft Store (WSDA), ce qui vous permettra d’avoir une certaine connaissance des WSDA avant d’aller plus loin.

Tout comme dans le cas des WSDAs, lorsque l’utilisateur d’une application source choisit d’imprimer quelque chose et navigue dans la boîte de dialogue d’impression, le système vérifie si une application de flux de travail est associée à cette imprimante. Si c’est le cas, l’application de flux de travail d’impression démarre (principalement en tant que tâche en arrière-plan ; plus loin). Une application de flux de travail peut modifier à la fois le ticket d’impression (document XML qui configure les paramètres de l’appareil d’imprimante pour la tâche d’impression actuelle) et le contenu XPS réel à imprimer. Elle peut éventuellement exposer cette fonctionnalité à l’utilisateur en lançant une interface utilisateur au milieu du processus. Après avoir effectué son travail, il transmet le contenu d’impression et le ticket d’impression au pilote.

Étant donné qu’elle implique des composants d’arrière-plan et de premier plan, et qu’elle est fonctionnellement couplée avec d’autres applications, une application de flux de travail d’impression peut être plus compliquée à implémenter que d’autres catégories d’applications UWP. Il est recommandé d’inspecter l’exemple d’application workflow tout en lisant ce guide pour mieux comprendre comment les différentes fonctionnalités peuvent être implémentées. Certaines fonctionnalités, telles que diverses vérifications d’erreur et gestion de l’interface utilisateur, sont absentes de ce guide pour la simplicité.

Mise en route

L’application de flux de travail doit indiquer son point d’entrée au système d’impression afin qu’elle puisse être lancée au moment approprié. Pour ce faire, insérez la déclaration suivante dans l’élément Application/Extensions du fichier package.appxmanifest du projet UWP.

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

Important

Il existe de nombreux scénarios dans lesquels la personnalisation de l’impression ne nécessite pas d’entrée utilisateur. Pour cette raison, les applications de flux de travail d’impression s’exécutent en tant que tâches en arrière-plan par défaut.

Si une application de flux de travail est associée à l’application source qui a démarré le travail d’impression (voir la section ultérieure pour obtenir des instructions sur ce problème), le système d’impression examine ses fichiers manifestes pour un point d’entrée de tâche en arrière-plan.

Effectuer un travail en arrière-plan sur le ticket d’impression

La première chose que fait le système d’impression avec l’application de flux de travail est d’activer sa tâche en arrière-plan (Dans ce cas, la WfBackgroundTask classe dans l’espace WFBackgroundTasks de noms). Dans la méthode de Run la tâche en arrière-plan, vous devez convertir les détails du déclencheur de la tâche en tant qu’instance PrintWorkflowTriggerDetails . Cela fournit les fonctionnalités spéciales d’une tâche en arrière-plan de flux de travail d’impression. Il expose la propriété PrintWorkflowSession, qui est une instance de PrintWorkFlowBackgroundSession. Les classes de session de flux de travail d’impression ( les variétés d’arrière-plan et de premier plan) contrôlent les étapes séquentielles de l’application de flux de travail d’impression.

Inscrivez ensuite les méthodes de gestionnaire pour les deux événements que cette classe de session déclenchera. Vous allez définir ces méthodes ultérieurement.

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();
}

Lorsque la Start méthode est appelée, le gestionnaire de sessions déclenche d’abord l’événement SetupRequested . Cet événement expose des informations générales sur la tâche d’impression, ainsi que le ticket d’impression. À ce stade, le ticket d’impression peut être modifié en arrière-plan.

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();

    // ...

Il est important de noter qu’il est important de gérer setupRequested que l’application détermine s’il faut lancer un composant de premier plan. Cela peut dépendre d’un paramètre précédemment enregistré dans le stockage local, ou d’un événement qui s’est produit pendant la modification du ticket d’impression, ou il peut s’agir d’un paramètre statique de votre application particulière.

// ...

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();

Effectuer un travail de premier plan sur le travail d’impression (facultatif)

Si la méthode SetRequiresUI a été appelée, le système d’impression examine le fichier manifeste du point d’entrée vers l’application de premier plan. L’élément Application/Extensions de votre fichier package.appxmanifest doit avoir les lignes suivantes. Remplacez la valeur par EntryPoint le nom de l’application de premier plan.

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

Ensuite, le système d’impression appelle la méthode OnActivated pour le point d’entrée d’application donné. Dans la méthode OnActivated de son fichier App.xaml.cs , l’application de flux de travail doit vérifier le type d’activation pour vérifier qu’il s’agit d’une activation de flux de travail. Dans ce cas, l’application de flux de travail peut convertir les arguments d’activation en objet PrintWorkflowUIActivatedEventArgs, qui expose un objet PrintWorkflowForegroundSession en tant que propriété. Cet objet, comme son équivalent en arrière-plan dans la section précédente, contient des événements déclenchés par le système d’impression, et vous pouvez affecter des gestionnaires à ces derniers. Dans ce cas, la fonctionnalité de gestion des événements est implémentée dans une classe distincte appelée WorkflowPage.

Tout d’abord, dans le fichier App.xaml.cs :

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();
    }
}

Une fois que l’interface utilisateur a attaché des gestionnaires d’événements et que la méthode OnActivated a quitté, le système d’impression déclenche l’événement SetupRequested pour que l’interface utilisateur soit gérée. Cet événement fournit les mêmes données que l’événement de configuration de tâche en arrière-plan fourni, y compris les informations sur le travail d’impression et le document de ticket d’impression, mais sans la possibilité de demander le lancement d’une interface utilisateur supplémentaire. Dans le fichier WorkflowPage.xaml.cs :

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();
    }
}

Ensuite, le système d’impression déclenche l’événement XpsDataAvailable pour l’interface utilisateur. Dans le gestionnaire de cet événement, l’application de flux de travail peut accéder à toutes les données disponibles pour l’événement d’installation et peut également lire directement les données XPS, en tant que flux d’octets bruts ou en tant que modèle objet. L’accès aux données XPS permet à l’interface utilisateur de fournir des services d’aperçu avant impression et de fournir des informations supplémentaires à l’utilisateur sur les opérations exécutées par l’application de flux de travail sur les données.

Dans le cadre de ce gestionnaire d’événements, l’application de flux de travail doit acquérir un objet de report s’il continuera d’interagir avec l’utilisateur. Sans report, le système d’impression prend en compte la tâche d’interface utilisateur terminée lorsque le gestionnaire d’événements XpsDataAvailable quitte ou lorsqu’il appelle une méthode asynchrone. Lorsque l’application a collecté toutes les informations requises à partir de l’interaction de l’utilisateur avec l’interface utilisateur, elle doit terminer le report afin que le système d’impression puisse ensuite avancer.

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();
}

En outre, l’instance PrintWorkflowSubmittedOperation exposée par les arguments d’événement fournit la possibilité d’annuler le travail d’impression ou d’indiquer que le travail a réussi, mais qu’aucun travail d’impression de sortie n’est nécessaire. Pour ce faire, appelez la méthode Complete avec une valeur PrintWorkflowSubmittedStatus.

Remarque

Si l’application de flux de travail annule le travail d’impression, il est vivement recommandé de fournir une notification toast indiquant pourquoi le travail a été annulé.

Effectuer un travail d’arrière-plan final sur le contenu d’impression

Une fois que l’interface utilisateur a terminé le report dans l’événement PrintTaskXpsDataAvailable (ou si l’étape de l’interface utilisateur a été ignorée), le système d’impression déclenche l’événement Envoyé pour la tâche en arrière-plan. Dans le gestionnaire de cet événement, l’application de flux de travail peut accéder à toutes les mêmes données fournies par l’événement XpsDataAvailable . Toutefois, contrairement à l’un des événements précédents, l’envoi fournit également un accès en écriture au contenu du travail d’impression final via une instance PrintWorkflowTarget.

L’objet utilisé pour mettre en pool les données pour l’impression finale dépend du fait que les données sources sont accessibles en tant que flux d’octets bruts ou en tant que modèle objet XPS. Lorsque l’application de flux de travail accède aux données sources via un flux d’octets, un flux d’octets de sortie est fourni pour écrire les données de travail finales. Lorsque l’application de flux de travail accède aux données sources via le modèle objet, un enregistreur de documents est fourni pour écrire des objets dans le travail de sortie. Dans les deux cas, l’application de flux de travail doit lire toutes les données sources, modifier toutes les données requises et écrire les données modifiées dans la cible de sortie.

Lorsque la tâche en arrière-plan termine l’écriture des données, elle doit appeler Complete sur l’objet PrintWorkflowSubmittedOperation correspondant. Une fois que l’application de flux de travail a terminé cette étape et que le gestionnaire d’événements Soumis s’arrête, la session de flux de travail est fermée et l’utilisateur peut surveiller l’état du travail d’impression final via les boîtes de dialogue d’impression standard.

Dernières étapes

Inscrire l’application de flux de travail d’impression sur l’imprimante

Votre application de flux de travail est associée à une imprimante à l’aide du même type de soumission de fichier de métadonnées que pour les WSDA. En fait, une application UWP unique peut agir à la fois comme une application de flux de travail et un WSDA qui fournit des fonctionnalités de paramètres de tâche d’impression. Suivez les étapes WSDA correspondantes pour créer l’association de métadonnées.

La différence est que si les WSDAs sont automatiquement activés pour l’utilisateur (l’application se lance toujours lorsque cet utilisateur imprime sur l’appareil associé), les applications de flux de travail ne sont pas. Ils ont une stratégie distincte qui doit être définie.

Définir la stratégie de l’application de flux de travail

La stratégie d’application de flux de travail est définie par les commandes PowerShell sur l’appareil qui doit exécuter l’application de flux de travail. Les commandes Set-Printer, Add-Printer (port existant) et Add-Printer (nouveau port WSD) seront modifiées pour autoriser la définition des stratégies de flux de travail.

  • Disabled: les applications de flux de travail ne sont pas activées.
  • Uninitialized: les applications de flux de travail sont activées si la DCA de flux de travail est installée dans le système. Si l’application n’est pas installée, l’impression continue.
  • Enabled: le contrat de flux de travail est activé si la DCA de flux de travail est installée dans le système. Si l’application n’est pas installée, l’impression échoue.

La commande suivante rend l’application de flux de travail requise sur l’imprimante spécifiée.

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

Un utilisateur local peut exécuter cette stratégie sur une imprimante locale ou, pour l’implémentation d’entreprise, l’administrateur de l’imprimante peut exécuter cette stratégie sur le serveur d’impression. La stratégie sera ensuite synchronisée avec toutes les connexions clientes. L’administrateur de l’imprimante peut utiliser cette stratégie chaque fois qu’une nouvelle imprimante est ajoutée.

Voir aussi

Exemple d’application de flux de travail

Espace de noms Windows.Graphics.Printing.Workflow