Erstellen und Verwenden eines App-Diensts

Wichtig

Die Codeauflistungen in diesem Thema sind nur C#. Eine App Service-Beispiel-App in C++/WinRT sowie C# finden Sie unter App Service-Beispiel-App.

App-Dienste sind UWP-Apps, die Dienste für andere UWP-Apps bereitstellen. Sie entsprechen Webdiensten auf einem Gerät. Ein App-Dienst wird als Hintergrundaufgabe in der Host-App ausgeführt und kann seine Dienste auch anderen Apps bereitstellen. Beispielsweise kann der Barcode-Scanner eines App-Dienstes auch anderen Apps nützlich sein. Oder vielleicht verfügt eine Enterprise-Suite von Apps über einen gemeinsamen App-Dienst zur Rechtschreibprüfung, der für die anderen Apps in der Suite verfügbar ist. Mit App-Diensten können Sie Dienste ohne Benutzeroberfläche erstellen, die Apps auf demselben Gerät und ab Windows 10, Version 1607, auch auf Remotegeräten aufrufen können.

Ab Windows 10, Version 1607, können Sie App-Dienste erstellen, die im gleichen Prozess wie die Vordergrund-App ausgeführt werden. Dieser Artikel konzentriert sich auf das Erstellen und Verwenden eines App-Diensts, der in einem separaten Hintergrundprozess ausgeführt wird. Weitere Informationen zum Ausführen eines App-Diensts im selben Prozess wie die Host-App finden Sie unter Konvertieren eines App-Diensts in demselben Prozess wie der Anbieter.

Erstellen eines neuen App-Dienstanbieterprojekts

In dieser Anleitung erstellen wir der Einfachheit halber alles in einer Projektmappe.

  1. Erstellen Sie in Visual Studio 2015 oder höher ein neues UWP-App-Projekt, und nennen Sie es AppServiceProvider.

    1. Wählen Sie Datei > Neues > Projekt... aus.
    2. Wählen Sie im Dialogfeld Neues Projekt erstellen die Option Leere App (Universelle Windows) C# aus. Dies ist die App, die den App-Dienst für andere UWP-Apps verfügbar macht.
    3. Klicken Sie auf Weiter, geben Sie dem Projekt den Namen AppServiceProvider, wählen Sie einen Speicherort dafür aus, und klicken Sie dann auf Erstellen.
  2. Wenn Sie aufgefordert werden, eine Ziel- und Mindestversion für das Projekt auszuwählen, wählen Sie mindestens 10.0.14393 aus. Wenn Sie das neue SupportsMultipleInstances-Attribut verwenden möchten, müssen Sie Visual Studio 2017 oder Visual Studio 2019 und 10.0.15063 (Windows 10 Creators Update) oder höher verwenden.

Hinzufügen einer App Service-Erweiterung zu Package.appxmanifest

Öffnen Sie im Projekt AppServiceProvider die Datei Package.appxmanifest in einem Text-Editor:

  1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste darauf.
  2. Wählen Sie Öffnen mit aus.
  3. Wählen Sie XML(Text)-Editor aus.

Fügen Sie die folgende AppService Erweiterung innerhalb des <Application> -Elements hinzu. Durch dieses Beispiel wird der com.microsoft.inventory-Dienst angekündigt, und die App wird als App-Dienstanbieter identifiziert. Der eigentliche Dienst wird als Hintergrundaufgabe implementiert. Das App Service-Projekt macht den Dienst für andere Apps verfügbar. Wir empfehlen, einen umgekehrten Domänennamen für den Dienstnamen zu verwenden.

Beachten Sie, dass das xmlns:uap4 Namespacepräfix und das uap4:SupportsMultipleInstances Attribut nur gültig sind, wenn Sie windows SDK Version 10.0.15063 oder höher als Ziel verwenden. Sie können sie sicher entfernen, wenn Sie ältere SDK-Versionen als Ziel verwenden.

Hinweis

Eine App Service-Beispiel-App in C++/WinRT sowie C# finden Sie unter App Service-Beispiel-App.

<Package
    ...
    xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
    xmlns:uap4="http://schemas.microsoft.com/appx/manifest/uap/windows10/4"
    ...
    <Applications>
        <Application Id="AppServiceProvider.App"
          Executable="$targetnametoken$.exe"
          EntryPoint="AppServiceProvider.App">
          ...
          <Extensions>
            <uap:Extension Category="windows.appService" EntryPoint="MyAppService.Inventory">
              <uap3:AppService Name="com.microsoft.inventory" uap4:SupportsMultipleInstances="true"/>
            </uap:Extension>
          </Extensions>
          ...
        </Application>
    </Applications>

Das Category Attribut identifiziert diese Anwendung als App-Dienstanbieter.

Das EntryPoint Attribut identifiziert die für den Namespace qualifizierte Klasse, die den Dienst implementiert, den wir als Nächstes implementieren werden.

Das SupportsMultipleInstances Attribut gibt an, dass der App-Dienst bei jedem Aufruf in einem neuen Prozess ausgeführt werden soll. Dies ist nicht erforderlich, steht Ihnen aber zur Verfügung, wenn Sie diese Funktionalität benötigen und das SDK 10.0.15063 (Windows 10 Creators Update) oder höher als Ziel verwenden. Außerdem sollte ihr der uap4 -Namespace vorangestellt werden.

Erstellen des App-Diensts

  1. Ein App-Dienst kann als Hintergrundaufgabe implementiert werden. Dadurch kann eine Vordergrundanwendung einen App-Dienst in einer anderen Anwendung aufrufen. Um einen App-Dienst als Hintergrundaufgabe zu erstellen, fügen Sie der Projektmappe (Datei > neues Projekt hinzufügen>) mit dem Namen MyAppService ein neues Windows-Runtime-Komponentenprojekt hinzu. Wählen Sie im Dialogfeld Neues Projekt hinzufügen die Option Installierte > Visual C# > -Windows-Runtime-Komponente (Universelles Windows) aus.

  2. Fügen Sie im Projekt AppServiceProvider einen Projekt-zu-Projekt-Verweis auf das neue MyAppService-Projekt hinzu (klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt AppServiceProvider-Projekt>Verweisprojekte>>hinzufügen>, und wählen Sie MyAppService>OK aus). Dieser Schritt ist wichtig, da der App-Dienst zur Laufzeit keine Verbindung herstellt, wenn Sie den Verweis nicht hinzufügen.

  3. Fügen Sie im Projekt MyAppService die folgenden using-Anweisungen am Anfang von Class1.cs hinzu:

    using Windows.ApplicationModel.AppService;
    using Windows.ApplicationModel.Background;
    using Windows.Foundation.Collections;
    
  4. Benennen Sie Class1.cs in Inventory.cs um, und ersetzen Sie den Stubcode für Class1 durch eine neue Hintergrundaufgabenklasse namens Inventory:

    public sealed class Inventory : IBackgroundTask
    {
        private BackgroundTaskDeferral backgroundTaskDeferral;
        private AppServiceConnection appServiceconnection;
        private String[] inventoryItems = new string[] { "Robot vacuum", "Chair" };
        private double[] inventoryPrices = new double[] { 129.99, 88.99 };
    
        public void Run(IBackgroundTaskInstance taskInstance)
        {
            // Get a deferral so that the service isn't terminated.
            this.backgroundTaskDeferral = taskInstance.GetDeferral();
    
            // Associate a cancellation handler with the background task.
            taskInstance.Canceled += OnTaskCanceled;
    
            // Retrieve the app service connection and set up a listener for incoming app service requests.
            var details = taskInstance.TriggerDetails as AppServiceTriggerDetails;
            appServiceconnection = details.AppServiceConnection;
            appServiceconnection.RequestReceived += OnRequestReceived;
        }
    
        private async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
        {
            // This function is called when the app service receives a request.
        }
    
        private void OnTaskCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
        {
            if (this.backgroundTaskDeferral != null)
            {
                // Complete the service deferral.
                this.backgroundTaskDeferral.Complete();
            }
        }
    }
    

    In dieser Klasse wird der App-Dienst ausgeführt.

    Run wird aufgerufen, wenn die Hintergrundaufgabe erstellt wird. Da Hintergrundaufgaben nach Abschluss der Ausführung beendet werden, nimmt der Code eine Verzögerung vor, sodass die Hintergrundaufgabe beim Verarbeiten von Anforderungen auf dem neuesten Stand bleibt. Ein App-Dienst, der als Hintergrundaufgabe implementiert ist, bleibt etwa 30 Sekunden lang am Leben, nachdem er einen Anruf empfangen hat, es sei denn, er wird innerhalb dieses Zeitfensters erneut aufgerufen oder eine Verzögerung wird gelöscht. Wenn der App-Dienst im gleichen Prozess wie der Aufrufer implementiert wird, ist die Lebensdauer des App-Diensts an die Lebensdauer des Aufrufers gebunden.

    Die Lebensdauer des App-Diensts hängt vom Aufrufer ab:

    • Wenn sich der Aufrufer im Vordergrund befindet, ist die Lebensdauer des App-Diensts identisch mit der des Aufrufers.
    • Wenn sich der Aufrufer im Hintergrund befindet, erhält der App-Dienst 30 Sekunden für die Ausführung. Wenn Sie eine Verzögerung durchführen, erhalten Sie eine zusätzliche Zeit von 5 Sekunden.

    OnTaskCanceled wird aufgerufen, wenn die Aufgabe abgebrochen wird. Die Aufgabe wird abgebrochen, wenn die Client-App die AppServiceConnection verwirft, die Client-App angehalten wird, das Betriebssystem heruntergefahren wird oder in den Standbymodus wechselt oder das Betriebssystem keine Ressourcen mehr zum Ausführen der Aufgabe hat.

Schreiben des Codes für den App-Dienst

OnRequestReceived ist der Ort, an dem der Code für den App-Dienst verwendet wird. Ersetzen Sie den Stub OnRequestReceived in der Datei "Inventory.cs" von MyAppService durch den Code aus diesem Beispiel. Dieser Code ruft einen Index für ein Bestandselement ab und übergibt ihn zusammen mit einer Befehlszeichenfolge an den Dienst, um den Namen und Preis des angegebenen Bestandselements abzurufen. Fügen Sie für Ihre eigenen Projekte Fehlerbehandlungscode hinzu.

private async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
{
    // Get a deferral because we use an awaitable API below to respond to the message
    // and we don't want this call to get canceled while we are waiting.
    var messageDeferral = args.GetDeferral();

    ValueSet message = args.Request.Message;
    ValueSet returnData = new ValueSet();

    string command = message["Command"] as string;
    int? inventoryIndex = message["ID"] as int?;

    if (inventoryIndex.HasValue &&
        inventoryIndex.Value >= 0 &&
        inventoryIndex.Value < inventoryItems.GetLength(0))
    {
        switch (command)
        {
            case "Price":
            {
                returnData.Add("Result", inventoryPrices[inventoryIndex.Value]);
                returnData.Add("Status", "OK");
                break;
            }

            case "Item":
            {
                returnData.Add("Result", inventoryItems[inventoryIndex.Value]);
                returnData.Add("Status", "OK");
                break;
            }

            default:
            {
                returnData.Add("Status", "Fail: unknown command");
                break;
            }
        }
    }
    else
    {
        returnData.Add("Status", "Fail: Index out of range");
    }

    try
    {
        // Return the data to the caller.
        await args.Request.SendResponseAsync(returnData);
    }
    catch (Exception e)
    {
        // Your exception handling code here.
    }
    finally
    {
        // Complete the deferral so that the platform knows that we're done responding to the app service call.
        // Note for error handling: this must be called even if SendResponseAsync() throws an exception.
        messageDeferral.Complete();
    }
}

Beachten Sie, dass OnRequestReceivedasync ist, da wir in diesem Beispiel einen erwartbaren Methodenaufruf für SendResponseAsync ausführen.

Eine Verzögerung wird durchgeführt, damit der Dienst asynchrone Methoden im OnRequestReceived-Handler verwenden kann. Dadurch wird sichergestellt, dass der Aufruf von OnRequestReceived erst abgeschlossen wird, wenn die Verarbeitung der Nachricht abgeschlossen ist. SendResponseAsync sendet das Ergebnis an den Aufrufer. SendResponseAsync signalisiert nicht den Abschluss des Aufrufs. Es ist der Abschluss der Verzögerung, der SendMessageAsync signalisiert, dass OnRequestReceived abgeschlossen wurde. Der Aufruf von SendResponseAsync wird in einen try/finally-Block eingeschlossen, da Sie die Verzögerung auch dann abschließen müssen, wenn SendResponseAsync eine Ausnahme auslöst.

App Services verwenden ValueSet-Objekte , um Informationen auszutauschen. Die Größe der Daten, die übergeben werden können, ist nur durch die Systemressourcen begrenzt. Es gibt keine vordefinierten Schlüssel zur Verwendung in Ihrem ValueSet. Sie müssen bestimmen, welche Schlüsselwerte Sie zum Definieren des Protokolls für Ihren App-Dienst verwenden. Dieses Protokoll muss beim Schreiben des Aufrufers berücksichtigt werden. In diesem Beispiel haben wir einen Schlüssel namens Command ausgewählt, der über einen Wert verfügt, der angibt, ob der App-Dienst den Namen des Bestandselements oder dessen Preis angeben soll. Der Index des Bestandsnamens wird unter dem ID Schlüssel gespeichert. Der Rückgabewert wird unter dem Result Schlüssel gespeichert.

An den Aufrufer wird eine AppServiceClosedStatus-Enumeration zurückgegeben, um anzugeben, ob der Aufruf des App-Diensts erfolgreich war. Ein Beispiel dafür, wie der Aufruf des App-Diensts fehlschlägt, ist, wenn das Betriebssystem den Dienstendpunkt abbricht, weil seine Ressourcen überschritten wurden. Sie können über ValueSet zusätzliche Fehlerinformationen zurückgeben. In diesem Beispiel verwenden wir einen Schlüssel namens Status , um detailliertere Fehlerinformationen an den Aufrufer zurückzugeben.

Der Aufruf von SendResponseAsync gibt ValueSet an den Aufrufer zurück.

Bereitstellen der Dienstanbieter-App und Abrufen des Paketfamiliennamens

Der App-Dienstanbieter muss bereitgestellt werden, bevor Sie ihn von einem Client aufrufen können. Sie können sie bereitstellen, indem Sie Projektmappe in Visual Studio erstellen auswählen>.

Sie benötigen auch den Paketfamiliennamen des App-Dienstanbieters, um ihn aufrufen zu können. Sie können sie abrufen, indem Sie die Datei Package.appxmanifest des AppServiceProvider-Projekts in der Designeransicht öffnen (doppelklicken Sie im Projektmappen-Explorer darauf). Wählen Sie die Registerkarte Verpackung aus, kopieren Sie den Wert neben Paketfamilienname, und fügen Sie ihn an einer stelle wie Editor ein.

Schreiben eines Clients zum Aufrufen des App-Diensts

  1. Fügen Sie der Projektmappe mit Datei Neues Projekt hinzufügen > ein neues leeres Windows Universal-App-Projekt >hinzu. Wählen Sie im Dialogfeld Neues Projekt hinzufügen die Option Installierte > Visual C# > Leere App (Universelle Windows) aus, und nennen Sie sie ClientApp.

  2. Fügen Sie im ClientApp-Projekt die folgende using-Anweisung am Anfang von MainPage.xaml.cs hinzu:

    using Windows.ApplicationModel.AppService;
    
  3. Fügen Sie ein Textfeld namens textBox und eine Schaltfläche zu MainPage.xaml hinzu.

  4. Fügen Sie einen Schaltflächenklickhandler für die Schaltfläche namens button_Click hinzu, und fügen Sie der Signatur des Schaltflächenhandlers den Schlüsselwort (keyword) async hinzu.

  5. Ersetzen Sie den Stub des Klickhandlers für die Schaltfläche durch den folgenden Code. Vergessen Sie nicht die inventoryService-Felddeklaration.

    private AppServiceConnection inventoryService;
    
    private async void button_Click(object sender, RoutedEventArgs e)
    {
       // Add the connection.
       if (this.inventoryService == null)
       {
           this.inventoryService = new AppServiceConnection();
    
           // Here, we use the app service name defined in the app service 
           // provider's Package.appxmanifest file in the <Extension> section.
           this.inventoryService.AppServiceName = "com.microsoft.inventory";
    
           // Use Windows.ApplicationModel.Package.Current.Id.FamilyName 
           // within the app service provider to get this value.
           this.inventoryService.PackageFamilyName = "Replace with the package family name";
    
           var status = await this.inventoryService.OpenAsync();
    
           if (status != AppServiceConnectionStatus.Success)
           {
               textBox.Text= "Failed to connect";
               this.inventoryService = null;
               return;
           }
       }
    
       // Call the service.
       int idx = int.Parse(textBox.Text);
       var message = new ValueSet();
       message.Add("Command", "Item");
       message.Add("ID", idx);
       AppServiceResponse response = await this.inventoryService.SendMessageAsync(message);
       string result = "";
    
       if (response.Status == AppServiceResponseStatus.Success)
       {
           // Get the data  that the service sent to us.
           if (response.Message["Status"] as string == "OK")
           {
               result = response.Message["Result"] as string;
           }
       }
    
       message.Clear();
       message.Add("Command", "Price");
       message.Add("ID", idx);
       response = await this.inventoryService.SendMessageAsync(message);
    
       if (response.Status == AppServiceResponseStatus.Success)
       {
           // Get the data that the service sent to us.
           if (response.Message["Status"] as string == "OK")
           {
               result += " : Price = " + response.Message["Result"] as string;
           }
       }
    
       textBox.Text = result;
    }
    

    Ersetzen Sie den Paketfamiliennamen in der Zeile this.inventoryService.PackageFamilyName = "Replace with the package family name"; durch den Paketfamiliennamen des AppServiceProvider-Projekts , den Sie oben unter Bereitstellen der Dienst-App abgerufen haben, und rufen Sie den Paketfamiliennamen ab.

    Hinweis

    Stellen Sie sicher, dass Sie das Zeichenfolgenliteral einfügen, anstatt es in eine Variable einzufügen. Es funktioniert nicht, wenn Sie eine Variable verwenden.

    Der Code richtet zunächst eine Verbindung mit dem App-Dienst ein. Die Verbindung bleibt geöffnet, bis Sie verwerfen this.inventoryService. Der App Service-Name muss mit dem AppService Attribut des Name Elements übereinstimmen, das Sie der Package.appxmanifest-Datei des AppServiceProvider-Projekts hinzugefügt haben. In diesem Beispiel lautet er <uap3:AppService Name="com.microsoft.inventory"/>.

    Ein ValueSet mit dem Namen message wird erstellt, um den Befehl anzugeben, den wir an den App-Dienst senden möchten. Der Beispiel-App-Dienst erwartet einen Befehl, der angibt, welche der beiden Aktionen ausgeführt werden soll. Wir rufen den Index aus dem Textfeld in der Client-App ab und rufen dann den Dienst mit dem Item Befehl auf, um die Beschreibung des Elements abzurufen. Anschließend rufen wir mit dem Befehl auf Price , um den Preis des Artikels zu erhalten. Der Text der Schaltfläche wird auf das Ergebnis festgelegt.

    Da AppServiceResponseStatus nur angibt, ob das Betriebssystem den Aufruf mit dem App-Dienst verbinden konnte, überprüfen wir den Status Schlüssel im ValueSet , das wir vom App-Dienst erhalten, um sicherzustellen, dass die Anforderung erfüllt werden konnte.

  6. Legen Sie das ClientApp-Projekt als Startprojekt fest (klicken Sie mit der rechten Maustaste darauf im Projektmappen-Explorer>Set as StartUp Project) und führen Sie die Projektmappe aus. Geben Sie 1 in das Textfeld ein, und klicken Sie auf die Schaltfläche. Der Dienst sollte „Stuhl: Preis = 88,99“ zurückgeben.

    Beispiel-App, die Stuhlpreis = 88,99 anzeigt

Wenn der App Service-Aufruf fehlschlägt, überprüfen Sie Folgendes im ClientApp-Projekt :

  1. Vergewissern Sie sich, dass der der Bestandsdienstverbindung zugewiesene Paketfamilienname mit dem Paketfamiliennamen der AppServiceProvider-App übereinstimmt. Sehen Sie sich die Zeile in button_Click mit this.inventoryService.PackageFamilyName = "...";an.
  2. Überprüfen Sie button_Click, ob der App-Dienstname, der der Inventurdienstverbindung zugewiesen ist, mit dem App-Dienstnamen in der Datei Package.appxmanifest des AppServiceProvider übereinstimmt. Weitere Informationen finden Sie unter this.inventoryService.AppServiceName = "com.microsoft.inventory";.
  3. Stellen Sie sicher, dass die AppServiceProvider-App bereitgestellt wurde. (Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf die Lösung, und wählen Sie Lösung bereitstellen aus.

Debuggen des App-Diensts

  1. Stellen Sie sicher, dass die Lösung vor dem Debuggen bereitgestellt wird, da die App-Dienstanbieter-App bereitgestellt werden muss, bevor der Dienst aufgerufen werden kann. (Klicken Sie in Visual Studio auf Erstellen > Projektmappe bereitstellen.)
  2. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt AppServiceProvider, und wählen Sie Eigenschaften aus. Ändern Sie auf der Registerkarte Debuggen die Startaktion in Eigenen Code zunächst nicht starten, sondern debuggen. (Hinweis: Wenn Sie C++ zum Implementieren Ihres App-Dienstanbieters verwendet haben, würden Sie auf der Registerkarte Debuggen Anwendung starten in Nein ändern.
  3. Legen Sie im Projekt MyAppService in der Datei Inventory.cs einen Haltepunkt in OnRequestReceived fest.
  4. Legen Sie das AppServiceProvider-Projekt als Startprojekt fest, und drücken Sie F5.
  5. Starten Sie ClientApp über das Startmenü (nicht über Visual Studio).
  6. Geben Sie 1 in das Textfeld ein, und klicken Sie auf die Schaltfläche. Der Debugger stoppt im App-Dienstaufruf am Haltepunkt in Ihrem App-Dienst.

Debuggen des Clients

  1. Befolgen Sie die Anweisungen im vorherigen Schritt, um den Client zu debuggen, der den App-Dienst aufruft.
  2. Starten Sie ClientApp über das Startmenü.
  3. Fügen Sie den Debugger an den ClientApp.exe-Prozess an (nicht an den ApplicationFrameHost.exe Prozess). (Klicken Sie in Visual Studio auf Debuggen > An den Prozess anhängen.)
  4. Legen Sie im ClientApp-Projekt einen Haltepunkt in button_Click fest.
  5. Die Haltepunkte sowohl im Client als auch im App-Dienst werden nun erreicht, wenn Sie die Zahl 1 in das Textfeld clientApp eingeben und auf die Schaltfläche klicken.

Allgemeine App Service-Problembehandlung

Wenn Sie nach dem Herstellen einer Verbindung mit einem App-Dienst eine AppUnavailable-status feststellen, überprüfen Sie Folgendes:

  • Stellen Sie sicher, dass das App-Dienstanbieterprojekt und das App Service-Projekt bereitgestellt werden. Beide müssen vor dem Ausführen des Clients bereitgestellt werden, da der Client andernfalls keine Verbindung herstellen kann. Sie können die Bereitstellung über Visual Studio mithilfe von BuildDeploy Solution (Projektmappe erstellen>) durchführen.
  • Stellen Sie im Projektmappen-Explorer sicher, dass Ihr App-Dienstanbieterprojekt über einen Projekt-zu-Projekt-Verweis auf das Projekt verfügt, das den App-Dienst implementiert.
  • Vergewissern Sie sich, dass der <Extensions> Eintrag und seine untergeordneten Elemente der Datei Package.appxmanifest hinzugefügt wurden, die zum App-Dienstanbieterprojekt gehört, wie oben unter Hinzufügen einer App Service-Erweiterung zu Package.appxmanifest angegeben.
  • Stellen Sie sicher, dass die Zeichenfolge AppServiceConnection.AppServiceName in Ihrem Client, der den App-Dienstanbieter aufruft, mit der <uap3:AppService Name="..." /> in der Datei Package.appxmanifest des App-Anbieterprojekts angegebenen übereinstimmt.
  • Stellen Sie sicher, dass appServiceConnection.PackageFamilyName mit dem Paketfamiliennamen der App-Dienstanbieterkomponente übereinstimmt, wie oben unter Hinzufügen einer App-Diensterweiterung zu Package.appxmanifest angegeben.
  • Überprüfen Sie für out-of-proc-App-Dienste, z. B. in diesem Beispiel, ob der EntryPoint im <uap:Extension ...> Element der Package.appxmanifest-Datei Ihres App-Dienstanbieterprojekts angegebene mit dem Namespace- und Klassennamen der öffentlichen Klasse übereinstimmt, die IBackgroundTask in Ihrem App Service-Projekt implementiert.

Behandeln von Problemen beim Debuggen

Wenn der Debugger nicht an Haltepunkten in Ihren App-Dienstanbieter- oder App Service-Projekten anhält, überprüfen Sie Folgendes:

  • Stellen Sie sicher, dass das App-Dienstanbieterprojekt und das App Service-Projekt bereitgestellt werden. Beide müssen vor dem Ausführen des Clients bereitgestellt werden. Sie können sie über Visual Studio bereitstellen, indem Sie projektmappe erstellen>.
  • Stellen Sie sicher, dass das Projekt, das Sie debuggen möchten, als Startprojekt festgelegt ist und dass die Debugeigenschaften für dieses Projekt so festgelegt sind, dass das Projekt nicht ausgeführt wird, wenn F5 gedrückt wird. Klicken Sie mit der rechten Maustaste auf das Projekt, klicken Sie dann auf Eigenschaften, und klicken Sie dann auf Debuggen (oder Debuggen in C++). Ändern Sie in C# die Startaktion in Nicht starten, sondern debuggen Sie meinen Code, wenn er gestartet wird. Legen Sie in C++ Anwendung starten auf Nein fest.

Hinweise

Dieses Beispiel bietet eine Einführung in das Erstellen eines App-Diensts, der als Hintergrundaufgabe ausgeführt wird, und den Aufruf von einer anderen App aus. Die wichtigsten Punkte, die sie beachten müssen, sind:

  • Erstellen Sie eine Hintergrundaufgabe zum Hosten des App-Diensts.
  • Fügen Sie die windows.appService Erweiterung zur Datei Package.appxmanifest des App-Anbieters hinzu.
  • Rufen Sie den Paketfamiliennamen des App-Dienstanbieters ab, damit wir eine Verbindung mit der Client-App herstellen können.
  • Fügen Sie dem App Service-Projektprojekt einen Projekt-zu-Projekt-Verweis aus dem App-Dienstanbieterprojekt hinzu.
  • Verwenden Sie Windows.ApplicationModel.AppService.AppServiceConnection , um den Dienst aufzurufen.

Vollständiger Code für „MyAppService”

using System;
using Windows.ApplicationModel.AppService;
using Windows.ApplicationModel.Background;
using Windows.Foundation.Collections;

namespace MyAppService
{
    public sealed class Inventory : IBackgroundTask
    {
        private BackgroundTaskDeferral backgroundTaskDeferral;
        private AppServiceConnection appServiceconnection;
        private String[] inventoryItems = new string[] { "Robot vacuum", "Chair" };
        private double[] inventoryPrices = new double[] { 129.99, 88.99 };

        public void Run(IBackgroundTaskInstance taskInstance)
        {
            // Get a deferral so that the service isn't terminated.
            this.backgroundTaskDeferral = taskInstance.GetDeferral();

            // Associate a cancellation handler with the background task.
            taskInstance.Canceled += OnTaskCanceled;

            // Retrieve the app service connection and set up a listener for incoming app service requests.
            var details = taskInstance.TriggerDetails as AppServiceTriggerDetails;
            appServiceconnection = details.AppServiceConnection;
            appServiceconnection.RequestReceived += OnRequestReceived;
        }

        private async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
        {
            // Get a deferral because we use an awaitable API below to respond to the message
            // and we don't want this call to get canceled while we are waiting.
            var messageDeferral = args.GetDeferral();

            ValueSet message = args.Request.Message;
            ValueSet returnData = new ValueSet();

            string command = message["Command"] as string;
            int? inventoryIndex = message["ID"] as int?;

            if (inventoryIndex.HasValue &&
                 inventoryIndex.Value >= 0 &&
                 inventoryIndex.Value < inventoryItems.GetLength(0))
            {
                switch (command)
                {
                    case "Price":
                        {
                            returnData.Add("Result", inventoryPrices[inventoryIndex.Value]);
                            returnData.Add("Status", "OK");
                            break;
                        }

                    case "Item":
                        {
                            returnData.Add("Result", inventoryItems[inventoryIndex.Value]);
                            returnData.Add("Status", "OK");
                            break;
                        }

                    default:
                        {
                            returnData.Add("Status", "Fail: unknown command");
                            break;
                        }
                }
            }
            else
            {
                returnData.Add("Status", "Fail: Index out of range");
            }

            // Return the data to the caller.
            await args.Request.SendResponseAsync(returnData);

            // Complete the deferral so that the platform knows that we're done responding to the app service call.
            // Note for error handling: this must be called even if SendResponseAsync() throws an exception.
            messageDeferral.Complete();
        }


        private void OnTaskCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
        {
            if (this.backgroundTaskDeferral != null)
            {
                // Complete the service deferral.
                this.backgroundTaskDeferral.Complete();
            }
        }
    }
}