Freigeben über


Anpassen des Druck-Workflows

Erstellen Sie benutzerdefinierte Druckworkflowfunktionen mithilfe einer Druckworkflow-App.

Überblick

Druckworkflow-Apps sind UWP-Apps, die die Funktionalität von Microsoft Store-Geräte-Apps (WSDAs)erweitern. Daher ist es hilfreich, sich mit WSDAs vertraut zu machen, bevor man fortfährt.

Genau wie bei WSDAs wählt der Benutzer einer Quellanwendung zunächst die Option zum Drucken aus. Während er durch das Druckdialogfeld navigiert, überprüft das System, ob eine Workflow-App mit diesem Drucker verknüpft ist. Wenn dies der Fall ist, wird die Druckworkflow-App gestartet (in erster Linie als Hintergrundaufgabe; mehr dazu unten). Eine Workflow-App kann sowohl das Druckticket (das XML-Dokument, das die Druckergeräteeinstellungen für die aktuelle Druckaufgabe konfiguriert) als auch den tatsächlichen XPS-Inhalt ändern, der gedruckt werden soll. Sie kann diese Funktionalität optional für den Benutzer verfügbar machen, indem eine Benutzeroberfläche mitten im Prozess gestartet wird. Nachdem sie ihre Arbeit ausgeführt hat, übergibt sie den Druckinhalt und das Druckticket an den Fahrer.

Da es Sich um Hintergrund- und Vordergrundkomponenten handelt und sie funktionell mit anderen Apps gekoppelt ist, kann eine Druckworkflow-App komplizierter implementiert werden als andere Kategorien von UWP-Apps. Es wird empfohlen, das Workflow-App-Beispiel zu überprüfen, während Sie dieses Handbuch lesen, um besser zu verstehen, wie die verschiedenen Features implementiert werden können. Einige Features, wie z. B. verschiedene Fehlerüberprüfungen und die Benutzeroberflächenverwaltung, fehlen aus diesem Leitfaden aus Gründen der Einfachheit.

Erste Schritte

Die Workflow-App muss ihren Einstiegspunkt in das Drucksystem angeben, damit sie zur entsprechenden Zeit gestartet werden kann. Dazu fügen Sie die folgende Deklaration in das Application/Extensions Element der Datei "package.appxmani fest" des UWP-Projekts ein.

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

Von Bedeutung

Es gibt viele Szenarien, in denen die Druckanpassung keine Benutzereingaben erfordert. Aus diesem Grund werden Druckworkflow-Apps standardmäßig als Hintergrundaufgaben ausgeführt.

Wenn eine Workflow-App der Quellanwendung zugeordnet ist, die den Druckauftrag gestartet hat (weitere Anweisungen hierzu finden Sie im späteren Abschnitt), überprüft das Drucksystem seine Manifestdateien auf einen Einstiegspunkt für Hintergrundaufgaben.

Hintergrundarbeit am Druckticket ausführen

Das erste, was das Drucksystem mit der Workflow-App ausführt, ist die Aktivierung der Hintergrundaufgabe (in diesem Fall die WfBackgroundTask Klasse im WFBackgroundTasks Namespace). In der Run-Methode der Hintergrundaufgabe sollten Sie die Triggerdetails der Aufgabe als PrintWorkflowTriggerDetails-Instanz umwandeln. Dadurch wird die spezielle Funktionalität für eine Hintergrundaufgabe für Druckworkflows bereitgestellt. Sie macht die PrintWorkflowSession-Eigenschaft verfügbar, bei der es sich um eine Instanz von PrintWorkFlowBackgroundSessionhandelt. Klassen von Druckworkflowsitzungen – sowohl die Hintergrund- als auch die Vordergrundtypen – kontrollieren die aufeinanderfolgenden Schritte der Druckworkflow-App.

Registrieren Sie dann Handlermethoden für die beiden Ereignisse, die diese Sitzungsklasse auslöst. Sie definieren diese Methoden später.

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

Wenn die Start-Methode aufgerufen wird, löst der Sitzungsmanager das SetupRequested Ereignis zuerst aus. Dieses Ereignis macht allgemeine Informationen über die Druckaufgabe sowie das Druckticket verfügbar. In dieser Phase kann das Druckticket im Hintergrund bearbeitet werden.

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

    // ...

Wichtig ist, dass die App bei der Verarbeitung von SetupRequested bestimmt, ob eine Vordergrundkomponente gestartet werden soll. Dies kann von einer Einstellung abhängen, die zuvor im lokalen Speicher gespeichert wurde, oder von einem Ereignis, das während der Bearbeitung des Drucktickets aufgetreten ist, oder es kann sich um eine statische Einstellung Ihrer jeweiligen App handeln.

// ...

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

Ausführen von Vordergrundarbeiten am Druckauftrag (optional)

Wenn die SetRequiresUI--Methode aufgerufen wurde, überprüft das Drucksystem die Manifestdatei, um den Einstiegspunkt der Vordergrundanwendung zu finden. Das Application/Extensions-Element Ihrer package.appxmanifest- Datei muss die folgenden Zeilen enthalten. Ersetzen Sie den Wert von EntryPoint durch den Namen der Vordergrundanwendung.

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

Als Nächstes ruft das Drucksystem die OnActivated-Methode für den angegebenen App-Einstiegspunkt auf. In der Methode OnActivated der Datei App.xaml.cs sollte die Workflow-App den Aktivierungstyp überprüfen, um festzustellen, ob es sich um eine Workflow-Aktivierung handelt. Wenn ja, kann die Workflow-App die Aktivierungsargumente in ein PrintWorkflowUIActivatedEventArgs Objekt umwandeln, das ein PrintWorkflowForegroundSession- -Objekt als Eigenschaft verfügbar macht. Dieses Objekt enthält, wie sein hintergrundbezogenes Gegenstück im vorherigen Abschnitt, Ereignisse, die vom Drucksystem ausgelöst werden, und Sie können diesen Handler zuweisen. In diesem Fall wird die Ereignisbehandlungsfunktion in einer separaten Klasse namens WorkflowPageimplementiert.

Zuerst in der Datei 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();
    }
}

Sobald die Benutzeroberfläche die Ereignishandler angefügt hat und die OnActivated-Methode beendet ist, löst das Drucksystem das SetupRequested Ereignis aus, damit die Benutzeroberfläche es behandeln kann. Dieses Ereignis enthält dieselben Daten wie das Ereignis zur Einrichtung von Hintergrundaufgaben, einschließlich der Druckauftragsinformationen und des Druckticketdokuments, ohne die Möglichkeit, den Start einer zusätzlichen Benutzeroberfläche zu initiieren. In der Datei 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();
    }
}

Als Nächstes löst das Drucksystem das Ereignis XpsDataAvailable für die UI aus. Im Ereignishandler kann die Workflow-App auf alle für das Einrichtungsereignis verfügbaren Daten zugreifen und die XPS-Daten zusätzlich direkt entweder als Datenstrom unformatierter Bytes oder als Objektmodell lesen. Der Zugriff auf die XPS-Daten ermöglicht es der Benutzeroberfläche, Druckvorschaudienste bereitzustellen und dem Benutzer zusätzliche Informationen zu den Vorgängen bereitzustellen, die von der Workflow-App für die Daten ausgeführt werden.

Im Rahmen dieses Ereignishandlers muss die Workflow-App ein Deferral-Objekt anfordern, wenn sie weiterhin mit dem Benutzer interagieren soll. Ohne Verzögerung wird die UI-Aufgabe vom Drucksystem als abgeschlossen betrachtet, wenn der XpsDataAvailable Ereignishandler beendet wird oder wenn er eine asynchrone Methode aufruft. Wenn die App alle erforderlichen Informationen aus der Interaktion des Benutzers mit der Benutzeroberfläche gesammelt hat, sollte der Aufschub abgeschlossen werden, damit das Drucksystem dann fortfahren kann.

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

Darüber hinaus bietet die PrintWorkflowSubmittedOperation Instanz, die durch die Ereignisargumente bereitgestellt wird, die Option, den Druckauftrag abzubrechen oder anzugeben, dass der Auftrag erfolgreich ist, aber kein Ausdruck erforderlich ist. Dazu rufen Sie die Complete-Methode mit einem PrintWorkflowSubmittedStatus--Wert auf.

Hinweis

Wenn die Workflow-App den Druckauftrag abbricht, wird dringend empfohlen, eine Toast-Benachrichtigung anzuzeigen, die angibt, warum der Auftrag abgebrochen wurde.

Ausführen der endgültigen Hintergrundarbeit für den Druckinhalt

Nachdem die Benutzeroberfläche die Verzögerung im PrintTaskXpsDataAvailable-Ereignis abgeschlossen hat (oder wenn der UI-Schritt umgangen wurde), löst das Drucksystem das Submitted-Ereignis für die Hintergrundaufgabe aus. Im Handler für dieses Ereignis kann die Workflow-App auf alle Daten zugreifen, die vom XpsDataAvailable--Ereignis bereitgestellt werden. Im Gegensatz zu jedem der vorherigen Ereignisse bietet Submitted jedoch auch Schreibzugriff auf den endgültigen Inhalt des Druckauftrags über eine PrintWorkflowTarget Instanz.

Das Objekt, das zum Spoolen der Daten für den endgültigen Druck verwendet wird, hängt davon ab, ob auf die Quelldaten als unformatierter Bytedatenstrom oder als XPS-Objektmodell zugegriffen wird. Wenn die Workflow-App über einen Byte-Stream auf die Quelldaten zugreift, wird ein Ausgabebyte-Stream bereitgestellt, in den die endgültigen Jobdaten geschrieben werden. Wenn die Workflow-App über das Objektmodell auf die Quelldaten zugreift, wird ein Dokumentschreiber bereitgestellt, um Objekte in den Ausgabeauftrag zu schreiben. In beiden Fällen sollte die Workflow-App alle Quelldaten lesen, alle erforderlichen Daten ändern und die geänderten Daten in das Ausgabeziel schreiben.

Wenn die Hintergrundaufgabe das Schreiben der Daten abgeschlossen hat, sollte sie Complete für das entsprechende PrintWorkflowSubmittedOperation-Objekt aufrufen. Sobald die Workflow-App diesen Schritt abgeschlossen hat und der Übermittelt-Ereignishandler beendet ist, wird die Workflowsitzung geschlossen, und der Benutzer kann in den Standarddruckdialogen den Status des endgültigen Druckauftrags überwachen.

Letzte Schritte

Registrieren Sie die Druckworkflow-App für den Drucker

Ihre Workflow-App ist einem Drucker zugeordnet, der dieselbe Art von Metadatendateiübermittlung wie für WSDAs verwendet. Tatsächlich kann eine einzelne UWP-Anwendung sowohl als Workflow-App als auch als WSDA fungieren, die Druckaufgabeneinstellungen bereitstellt. Führen Sie die entsprechenden WSDA-Schritte zum Erstellen der Metadatenzuordnungaus.

Der Unterschied besteht darin, dass WSDAs automatisch für den Benutzer aktiviert werden (die App wird immer gestartet, wenn dieser Benutzer auf dem zugeordneten Gerät druckt), während Workflow-Apps dies nicht sind. Sie verfügen über eine separate Richtlinie, die festgelegt werden muss.

Die Richtlinie der Workflow-App festlegen

Die Workflow-App-Richtlinie wird von PowerShell-Befehlen auf dem Gerät festgelegt, auf dem die Workflow-App ausgeführt werden soll. Die Befehle "Set-Printer", Add-Printer (vorhandener Port) und Add-Printer (neuer WSD-Port) werden so geändert, dass Workflowrichtlinien festgelegt werden können.

  • Disabled: Workflow-Apps werden nicht aktiviert.
  • Uninitialized: Workflow-Apps werden aktiviert, wenn der Workflow-DCA im System installiert ist. Wenn die App nicht installiert ist, wird der Druckvorgang weiterhin fortgesetzt.
  • Enabled: Workflow-Vertrag wird aktiviert, wenn der Workflow-DCA im System installiert ist. Wenn die App nicht installiert ist, schlägt das Drucken fehl.

Mit dem folgenden Befehl wird die Workflow-App auf dem angegebenen Drucker zur Pflicht.

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

Ein lokaler Benutzer kann diese Richtlinie auf einem lokalen Drucker ausführen, oder für die Unternehmensimplementierung kann der Druckeradministrator diese Richtlinie auf dem Druckserver ausführen. Die Richtlinie wird anschließend mit allen Client-Verbindungen synchronisiert. Der Druckeradministrator kann diese Richtlinie immer dann verwenden, wenn ein neuer Drucker hinzugefügt wird.

Siehe auch

Workflow-App-Beispiel-

Windows.Graphics.Printing.Workflow-Namensraum