Personalizzare il flusso di lavoro di stampaCustomize the print workflow

PanoramicaOverview

Gli sviluppatori possono personalizzare l'esperienza di stampa del flusso di lavoro tramite l'uso di un'applicazione di flusso di lavoro stampa.Developers can customize the printing workflow experience through the use of a print workflow app. Le app per flussi di lavoro di stampa sono app UWP che si espandono sulla funzionalità delle app per dispositivi Microsoft Store (WSDAs), pertanto è utile avere una certa familiarità con WSDAs prima di proseguire.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.

Come nel caso di WSDAs, quando l'utente di un'applicazione di origine sceglie di stampare qualcosa e passa attraverso la finestra di dialogo di stampa, il sistema verifica se un'app del flusso di lavoro è associata a tale stampante.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. In caso contrario, l'app del flusso di lavoro di stampa viene avviata (principalmente come attività in background, più avanti in questa sezione).If it is, the print workflow app launches (primarily as a background task; more on this below). Un'applicazione flusso di lavoro è in grado di modificare sia il Print Ticket (il documento XML che configura le impostazioni del dispositivo stampante per l'attività di stampa corrente) sia il contenuto XPS effettivo da stampare.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. Facoltativamente, può esporre questa funzionalità all'utente avviando un'interfaccia utente a metà del processo.It can optionally expose this functionality to the user by launching a UI midway through the process. Al termine dell'operazione, il contenuto di stampa e il ticket di stampa vengono passati al driver.After doing its work, it passes the print content and print ticket on to the driver.

Poiché comporta componenti in background e in primo piano e dal punto di vista funzionale associato ad altre app, un'app per flussi di lavoro di stampa può essere più complessa da implementare rispetto ad altre categorie di app 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. È consigliabile esaminare l' esempio di app del flusso di lavoro leggendo questa guida per comprendere meglio il modo in cui possono essere implementate le diverse funzionalità.It is recommended that you inspect the Workflow app sample while reading this guide to better understand how the different features can be implemented. Alcune funzionalità, ad esempio i vari controlli degli errori e la gestione dell'interfaccia utente, sono assenti da questa guida per motivi di semplicità.Some features, such as various error checks and UI management, are absent from this guide for the sake of simplicity.

Guida introduttivaGetting started

L'app del flusso di lavoro deve indicare il punto di ingresso al sistema di stampa, in modo che possa essere avviata al momento appropriato.The workflow app must indicate its entry point to the print system so that it can be launched at the appropriate time. Questa operazione viene eseguita inserendo la dichiarazione seguente nell' Application/Extensions elemento del file Package. appxmanifest del progetto UWP.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" />

Importante

Esistono molti scenari in cui la personalizzazione di stampa non richiede l'input dell'utente.There are many scenarios in which the print customization does not require user input. Per questo motivo, le app del flusso di lavoro di stampa vengono eseguite come attività in background per impostazione predefinita.For this reason, Print workflow apps run as background tasks by default.

Se un'app del flusso di lavoro è associata all'applicazione di origine che ha avviato il processo di stampa (vedere la sezione successiva per istruzioni su questo), il sistema di stampa esamina i file manifesto per un punto di ingresso dell'attività in background.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.

Eseguire operazioni in background sul ticket di stampaDo background work on the print ticket

La prima cosa che il sistema di stampa esegue con l'app del flusso di lavoro è attivare l'attività in background, in questo caso la WfBackgroundTask classe nello WFBackgroundTasks spazio dei nomi.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). Nel metodo dell'attività in background Run è necessario eseguire il cast dei dettagli del trigger dell'attività come istanza di PrintWorkflowTriggerDetails .In the background task's Run method, you should cast the task's trigger details as a PrintWorkflowTriggerDetails instance. Questo fornirà la funzionalità speciale per un'attività in background del flusso di lavoro di stampa.This will provide the special functionality for a print workflow background task. Espone la proprietà PrintWorkflowSession , che è un'istanza di PrintWorkFlowBackgroundSession.It exposes the PrintWorkflowSession property, which is an instance of PrintWorkFlowBackgroundSession. Classi di sessione del flusso di lavoro di stampa: le varietà in background e in primo piano controllano i passaggi sequenziali dell'app flusso di lavoro di stampa.Print workflow session classes - both the background and foreground varieties - will control the sequential steps of the print workflow app.

Registrare quindi i metodi del gestore per i due eventi che questa classe di sessione genererà.Then register handler methods for the two events that this session class will raise. Questi metodi vengono definiti in un secondo momento.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();
}

Quando Start viene chiamato il metodo, il gestore sessioni genera prima l'evento SetupRequested .When the Start method is called, the session manager will raise the SetupRequested event first. Questo evento espone informazioni generali sull'attività di stampa, nonché sul ticket di stampa.This event exposes general information about the print task, as well as the print ticket. In questa fase, il Print Ticket può essere modificato in background.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();

    // ...

Un aspetto importante è la gestione del SetupRequested che l'app determinerà se avviare un componente in primo piano.Importantly, it is in the handling of the SetupRequested that the app will determine whether to launch a foreground component. Questo può dipendere da un'impostazione salvata in precedenza nella risorsa di archiviazione locale o da un evento che si è verificato durante la modifica del ticket di stampa oppure un'impostazione statica dell'app specifica.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();

Eseguire operazioni in primo piano nel processo di stampa (facoltativo)Do foreground work on the print job (optional)

Se è stato chiamato il metodo SetRequiresUI , il sistema di stampa analizzerà il file manifesto per il punto di ingresso all'applicazione in primo piano.If the SetRequiresUI method was called, then the print system will examine the manifest file for the entry point to the foreground application. L' Application/Extensions elemento del file Package. appxmanifest deve contenere le righe seguenti.The Application/Extensions element of your package.appxmanifest file must have the following lines. Sostituire il valore di EntryPoint con il nome dell'app in primo piano.Replace the value of EntryPoint with name of the foreground app.

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

Successivamente, il sistema di stampa chiama il metodo OnActivated per il punto di ingresso dell'app specificato.Next, the print system calls the OnActivated method for the given app entry point. Nel metodo OnActivated del file app.XAML.cs , l'app del flusso di lavoro deve controllare il tipo di attivazione per verificare che si tratta di un'attivazione del flusso di lavoro.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. In tal caso, l'app del flusso di lavoro può eseguire il cast degli argomenti di attivazione a un oggetto PrintWorkflowUIActivatedEventArgs , che espone un oggetto PrintWorkflowForegroundSession come proprietà.If so, the workflow app can cast the activation arguments to a PrintWorkflowUIActivatedEventArgs object, which exposes a PrintWorkflowForegroundSession object as a property. Questo oggetto, come la relativa controparte in background nella sezione precedente, contiene gli eventi generati dal sistema di stampa ed è possibile assegnare i gestori a tali oggetti.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. In questo caso, la funzionalità di gestione degli eventi verrà implementata in una classe separata denominata WorkflowPage .In this case, the event-handling functionality will be implemented in a separate class called WorkflowPage.

Per prima cosa, nel file 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();
    }
}

Una volta che l'interfaccia utente ha associato i gestori eventi e il metodo OnActivated è stato terminato, il sistema di stampa genererà l'evento SetupRequested per la gestione dell'interfaccia utente.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. Questo evento fornisce gli stessi dati forniti dall'evento di configurazione dell'attività in background, incluse le informazioni sul processo di stampa e il documento del ticket di stampa, ma senza la possibilità di richiedere l'avvio di un'interfaccia utente aggiuntiva.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. Nel file 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();
    }
}

Successivamente, il sistema di stampa genererà l'evento XpsDataAvailable per l'interfaccia utente.Next, the print system will raise the XpsDataAvailable event for the UI. Nel gestore per questo evento, l'app del flusso di lavoro può accedere a tutti i dati disponibili per l'evento di installazione e può inoltre leggere direttamente i dati XPS, come un flusso di byte non elaborati o come modello a oggetti.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. L'accesso ai dati XPS consente all'interfaccia utente di fornire servizi di anteprima di stampa e fornire all'utente informazioni aggiuntive sulle operazioni che l'app del flusso di lavoro eseguirà sui dati.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.

Come parte di questo gestore eventi, l'app del flusso di lavoro deve acquisire un oggetto rinvio se continuerà a interagire con l'utente.As part of this event handler, the workflow app must acquire a deferral object if it will continue to interact with the user. Senza rinvio, il sistema di stampa considererà l'attività dell'interfaccia utente completata quando il gestore dell'evento XpsDataAvailable viene chiuso o quando chiama un metodo asincrono.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. Quando l'app ha raccolto tutte le informazioni necessarie dall'interazione dell'utente con l'interfaccia utente, deve completare il rinvio, in modo che il sistema di stampa possa avanzare.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();
}

Inoltre, l'istanza di PrintWorkflowSubmittedOperation esposta dagli argomenti dell'evento fornisce l'opzione per annullare il processo di stampa o per indicare che il processo ha esito positivo ma che non sarà necessario alcun processo di stampa di output.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. Questa operazione viene eseguita chiamando il metodo complete con un valore PrintWorkflowSubmittedStatus .This is done by calling the Complete method with a PrintWorkflowSubmittedStatus value.

Nota

Se l'app del flusso di lavoro Annulla il processo di stampa, è consigliabile fornire una notifica di tipo avviso popup indicante il motivo per cui il processo è stato annullato.If the workflow app cancels the print job, it is highly recommended that it provide a toast notification indicating why the job was cancelled.

Eseguire il lavoro in background finale sul contenuto di stampaDo final background work on the print content

Una volta che l'interfaccia utente ha completato il rinvio nell'evento PrintTaskXpsDataAvailable (o se il passaggio dell'interfaccia utente è stato ignorato), il sistema di stampa genererà l'evento inviato per l'attività in background.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. Nel gestore per questo evento, l'app del flusso di lavoro può ottenere l'accesso a tutti gli stessi dati forniti dall'evento XpsDataAvailable .In the handler for this event, the workflow app can get access to all of the same data provided by the XpsDataAvailable event. Tuttavia, a differenza di uno degli eventi precedenti, l' invio fornisce anche l'accesso in scrittura al contenuto finale del processo di stampa tramite un'istanza di PrintWorkflowTarget .However, unlike any of the previous events, Submitted also provides write access to the final print job content through a PrintWorkflowTarget instance.

L'oggetto utilizzato per eseguire lo spooling dei dati per la stampa finale varia a seconda che si acceda ai dati di origine come flusso di byte non elaborato o come modello a oggetti 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. Quando l'app del flusso di lavoro accede ai dati di origine tramite un flusso di byte, viene fornito un flusso di byte di output in cui scrivere i dati del processo finale.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. Quando l'app del flusso di lavoro accede ai dati di origine tramite il modello a oggetti, viene fornito un writer di documenti per scrivere oggetti nel processo di output.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 entrambi i casi, l'app del flusso di lavoro deve leggere tutti i dati di origine, modificare i dati necessari e scrivere i dati modificati nella destinazione di output.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.

Quando l'attività in background termina la scrittura dei dati, deve chiamare complete sull'oggetto PrintWorkflowSubmittedOperation corrispondente.When the background task finishes writing the data, it should call Complete on the corresponding PrintWorkflowSubmittedOperation object. Una volta che l'app del flusso di lavoro ha completato questo passaggio e il gestore eventi inviato è stato chiuso, la sessione del flusso di lavoro viene chiusa e l'utente può monitorare lo stato del processo di stampa finale tramite le finestre di dialogo di stampa standard.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.

Passaggi finaliFinal steps

Registrare l'app del flusso di lavoro di stampa sulla stampanteRegister the print workflow app to the printer

L'app del flusso di lavoro è associata a una stampante che usa lo stesso tipo di invio di file di metadati di WSDAs.Your workflow app is associated with a printer using the same type of metadata file submission as for WSDAs. Infatti, una singola applicazione UWP può fungere sia da un'app del flusso di lavoro che da un WSDA che fornisce funzionalità di impostazioni delle attività di stampa.In fact, a single UWP application can act as both a workflow app and a WSDA that provides print task settings functionality. Per creare l'associazione di metadati, attenersi alla procedura WSDA corrispondente.Follow the corresponding WSDA steps for creating the metadata association.

La differenza è che, mentre i WSDAs vengono attivati automaticamente per l'utente (l'app verrà sempre avviata quando l'utente stampa sul dispositivo associato), le app per i flussi di lavoro non lo sono.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. Hanno un criterio separato che è necessario impostare.They have a separate policy that must be set.

Impostare i criteri dell'app del flusso di lavoroSet the workflow app's policy

I criteri dell'app del flusso di lavoro vengono impostati dai comandi di PowerShell nel dispositivo che esegue l'app del flusso di lavoro.The workflow app policy is set by Powershell commands on the device that is to run the workflow app. I comandi set-Printer, Add-Printer (porta esistente) e Add-Printer (nuova porta WSD) verranno modificati per consentire l'impostazione dei criteri del flusso di lavoro.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: Le app del flusso di lavoro non verranno attivate.Disabled: Workflow apps will not be activated.
  • Uninitialized: Le app del flusso di lavoro verranno attivate se il DCA del flusso di lavoro è installato nel sistema.Uninitialized: Workflow apps will be activated if the Workflow DCA is installed in the system. Se l'app non è installata, la stampa continuerà comunque.If the app is not installed, printing will still proceed.
  • Enabled: Il contratto del flusso di lavoro verrà attivato se il DCA del flusso di lavoro è installato nel sistema.Enabled: Workflow contract will be activated if the Workflow DCA is installed in the system. Se l'app non è installata, la stampa avrà esito negativo.If the app is not installed, printing will fail.

Il seguente comando rende l'app del flusso di lavoro necessaria sulla stampante specificata.The following command makes the workflow app required on the specified printer.

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

Un utente locale può eseguire questo criterio in una stampante locale oppure, per l'implementazione aziendale, l'amministratore della stampante può eseguire questo criterio nel server di stampa.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. Il criterio verrà quindi sincronizzato con tutte le connessioni client.The policy will then be synchronized to all client connections. L'amministratore della stampante può utilizzare questi criteri ogni volta che viene aggiunta una nuova stampante.The printer admin can use this policy whenever a new printer is added.

Vedere ancheSee also

Esempio di app WorkflowWorkflow app sample

Spazio dei nomi Windows. graphics. Printing. WorkflowWindows.Graphics.Printing.Workflow namespace