Freigeben über


Erstellen und Verwenden eines App-Diensts

Wichtig

Die Codeauflistungen in diesem Thema sind nur C#. Eine App-Beispiel-App in C++/WinRT sowie C# finden Sie unter App-Dienstbeispiel-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 eine Enterprise-App-Suite verfügt über einen allgemeinen App-Dienst für die 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 im selben Prozess wie der Anbieter.

Erstellen eines neuen App-Dienstanbieterprojekts

In dieser Vorgehensweise erstellen wir alles in einer Lösung zur Einfachheit.

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

    1. > > Neues Projekt auswählen...
    2. Wählen Sie im Dialogfeld "Neues Projekt erstellen" die Option "Leere App ( Universelle Windows-App) C# aus. Dies ist die App, die den App-Dienst anderen UWP-Apps zur Verfügung stellt.
    3. Klicken Sie auf "Weiter", geben Sie dem Projekt "AppServiceProvider" einen Namen, 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 Attribut "SupportsMultipleInstances " verwenden möchten, müssen Sie Visual Studio 2017 oder Visual Studio 2019 und das Ziel 10.0.15063 (Windows 10 Creators Update) oder höher verwenden.

Hinzufügen einer App-Diensterweiterung 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-Editor (Text) aus.

Fügen Sie die folgende AppService Erweiterung innerhalb des <Application> Elements hinzu. In diesem Beispiel wird der com.microsoft.inventory Dienst angekündigt und identifiziert diese App als App-Dienstanbieter. Der eigentliche Dienst wird als Hintergrundaufgabe implementiert. Das App-Dienstprojekt macht den Dienst für andere Apps verfügbar. Es wird empfohlen, einen umgekehrten Domänennamenstil 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 die Windows SDK-Version 10.0.15063 oder höher verwenden. Sie können sie sicher entfernen, wenn Sie auf ältere SDK-Versionen abzielen.

Hinweis

Eine App-Beispiel-App in C++/WinRT sowie C# finden Sie unter App-Dienstbeispiel-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 namespacequalifizierte Klasse, die den Dienst implementiert, den wir als Nächstes implementieren.

Das SupportsMultipleInstances Attribut gibt an, dass jedes Mal, wenn der App-Dienst aufgerufen wird, in einem neuen Prozess ausgeführt werden soll. Dies ist nicht erforderlich, steht Ihnen jedoch zur Verfügung, wenn Sie diese Funktionalität benötigen und auf das 10.0.15063 SDK (Windows 10 Creators Update) oder höher abzielen. Es sollte auch vom uap4 Namespace vorgestellt werden.

Erstellen des App-Dienstes

  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 (File > Add > New Project) ein neues Windows-Runtime-Komponentenprojekt mit dem Namen "MyAppService" hinzu. Wählen Sie im Dialogfeld "Neues Projekt hinzufügen" die Option "Visual > C# > Windows-Runtime Komponente (Universelle Windows-Komponente)" aus.

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

  3. Fügen Sie im MyAppService-Projekt 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 seine Arbeit erledigen.

    "Ausführen" wird aufgerufen, wenn die Hintergrundaufgabe erstellt wird. Da Hintergrundaufgaben nach Abschluss der Ausführung beendet werden, löst der Code eine Verzögerung aus, sodass die Hintergrundaufgabe weiterhin Anforderungen bedient. Ein App-Dienst, der als Hintergrundaufgabe implementiert wird, bleibt etwa 30 Sekunden aktiv, nachdem er einen Anruf empfängt, es sei denn, er wird innerhalb dieses Zeitfensters erneut aufgerufen oder eine Verzögerung wird beendet. 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, entspricht die Lebensdauer des App-Diensts dem Aufrufer.
    • Wenn sich der Aufrufer im Hintergrund befindet, wird der App-Dienst 30 Sekunden ausgeführt. Das Abstellen einer Verzögerung bietet eine zusätzliche Einmalzeit von 5 Sekunden.

    OnTaskCanceled wird aufgerufen, wenn die Aufgabe abgebrochen wird. Die Aufgabe wird abgebrochen, wenn die Client-App die AppServiceConnection verworfen, die Client-App angehalten wird, das Betriebssystem heruntergefahren oder in den Ruhezustand wechselt oder das Betriebssystem nicht mehr Ressourcen zum Ausführen der Aufgabe ausführt.

Schreiben des Codes für den App-Dienst

OnRequestReceived ist der Ort, an dem der Code für den App-Dienst abgelegt wird. Ersetzen Sie den Stub OnRequestReceived in der 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 den Preis des angegebenen Bestandselements abzurufen. Fügen Sie für Ihre eigenen Projekte Code zur Fehlerbehandlung 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 OnRequestReceived asynchron ist, da wir in diesem Beispiel einen wartenden Methodenaufruf an SendResponseAsync vornehmen.

Es wird eine Verzögerung ausgefü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 Anrufs. Es ist der Abschluss der Verzögerung, die signalisiert SendMessageAsync , dass OnRequestReceived abgeschlossen wurde. Der Aufruf von SendResponseAsync wird in einen Try/finally-Block umschlossen, da Sie die Verzögerung abschließen müssen, auch wenn SendResponseAsync eine Ausnahme auslöst.

App-Dienste verwenden ValueSet-Objekte , um Informationen auszutauschen. Die Größe der Daten, die Sie übergeben können, ist nur durch Systemressourcen begrenzt. Es gibt keine vordefinierten Schlüssel, die Sie in Ihrem ValueSet verwenden können. Sie müssen bestimmen, welche Schlüsselwerte Sie verwenden, um das Protokoll für Ihren App-Dienst zu definieren. Der Aufrufer muss mit diesem Protokoll geschrieben werden. In diesem Beispiel haben wir einen Schlüssel mit dem Namen " Command Wert" ausgewählt, 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.

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

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

Bereitstellen der Dienst-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 bereitstellen" auswählen.>

Außerdem benötigen Sie den Paketfamiliennamen des App-Dienstanbieters, um ihn aufzurufen. Sie können die Datei abrufen, indem Sie die Datei "Package.appxmanifest" des AppServiceProvider-Projekts in der Designeransicht öffnen (doppelklicken Sie in der Projektmappen-Explorer darauf). Wählen Sie die Registerkarte "Verpackung " aus, kopieren Sie den Wert neben dem Paketfamiliennamen, und fügen Sie ihn an einer beliebigen Stelle wie Editor für den nächsten Schritt ein.

Schreiben eines Clients zum Aufrufen des App-Diensts

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

  2. Fügen Sie im ClientApp-Projekt oben in MainPage.xaml.cs die folgende using-Anweisung 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 das Schlüsselwort asynchron zur Signatur des Schaltflächenhandlers hinzu.

  5. Ersetzen Sie den Stub ihres Schaltflächenklickhandlers durch den folgenden Code. Achten Sie darauf, die inventoryService Felddeklaration einzuschließen.

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

    Ein ValueSet-Name 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 von zwei Aktionen ausgeführt werden sollen. 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 führen wir den Aufruf mit dem Price Befehl aus, um den Preis des Artikels zu erhalten. Der Schaltflächentext 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 Wertsatz , den wir vom App-Dienst erhalten, um sicherzustellen, dass er die Anforderung erfüllen konnte.

  6. Legen Sie das ClientApp-Projekt als Startprojekt fest (klicken Sie mit der rechten Maustaste im Projektmappen-Explorer> Set als StartProjekt) und führen Sie die Projektmappe aus. Geben Sie die Zahl 1 in das Textfeld ein, und klicken Sie auf die Schaltfläche. Sie sollten "Stuhl : Preis = 88,99" zurück vom Dienst erhalten.

    Beispiel-App mit Stuhlpreis=88,99

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

  1. Stellen Sie sicher, dass der Paketfamilienname, der der Bestandsdienstverbindung zugewiesen ist, dem Paketfamiliennamen der App AppServiceProvider entspricht. Sehen Sie sich die Zeile in button_Click mit this.inventoryService.PackageFamilyName = "...";.
  2. Überprüfen Sie in button_Click, ob der Name des App-Diensts, der der Bestandsdienstverbindung zugewiesen ist, dem App-Dienstnamen in der Datei "Package.appxmanifest" von AppServiceProvider entspricht. Siehe: this.inventoryService.AppServiceName = "com.microsoft.inventory";.
  3. Stellen Sie sicher, dass die AppServiceProvider-App bereitgestellt wurde. (Im Projektmappen-Explorer klicken Sie 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 des App-Dienstanbieters bereitgestellt werden muss, bevor der Dienst aufgerufen werden kann. (In Visual Studio, Build > Deploy Solution).
  2. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das AppServiceProvider-Projekt, und wählen Sie "Eigenschaften" aus. Ändern Sie auf der Registerkarte "Debuggen " die Startaktion in "Nicht starten", sondern debuggen Sie meinen Code, wenn sie gestartet wird. (Hinweis: Wenn Sie C++ zum Implementieren Ihres App-Dienstanbieters verwendet haben, aus dem Die Registerkarte "Debuggen" würde "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 aus dem Menü (nicht aus Visual Studio).
  6. Geben Sie die Zahl 1 in das Textfeld ein, und drücken Sie die Schaltfläche. Der Debugger wird im App-Dienstaufruf am Haltepunkt in Ihrem App-Dienst beendet.

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" aus dem Menü .
  3. Fügen Sie den Debugger an den ClientApp.exe Prozess an (nicht den ApplicationFrameHost.exe Prozess). (Wählen Sie in Visual StudioDebug > Attach to Process....)
  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 Problembehandlung beim App-Dienst

Wenn nach dem Versuch, eine Verbindung mit einem App-Dienst herzustellen, ein AppUnavailable-Status auftritt, überprüfen Sie Folgendes:

  • Stellen Sie sicher, dass das Projekt des App-Dienstanbieters und das App-Dienstprojekt bereitgestellt werden. Beide müssen bereitgestellt werden, bevor der Client ausgeführt wird, da andernfalls der Client keine Verbindung herstellen kann. Sie können aus Visual Studio bereitstellen, indem Sie die Buildbereitstellungslösung> verwenden.
  • 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 die untergeordneten Elemente der Datei "Package.appxmanifest " zum App-Dienstanbieterprojekt hinzugefügt wurden, wie oben in "Hinzufügen einer App-Diensterweiterung zu Package.appxmanifest" angegeben.
  • Stellen Sie sicher, dass die Zeichenfolge "AppServiceConnection.AppServiceName" in Ihrem Client, die den App-Dienstanbieter aufruft, dem <uap3:AppService Name="..." /> in der Datei "Package.appxmanifest" des App-Dienstanbieterprojekts entspricht.
  • Stellen Sie sicher, dass der AppServiceConnection.PackageFamilyName dem Paketfamiliennamen der App-Dienstanbieterkomponente entspricht, wie oben in "Hinzufügen einer App-Diensterweiterung zu Package.appxmanifest" angegeben.
  • Überprüfen Sie EntryPoint <uap:Extension ...> für out-of-proc-App-Dienste wie die in diesem Beispiel angegebene Datei des App-Dienstanbieterprojekts "Package.appxmanifest" mit dem Namespace und dem Klassennamen der öffentlichen Klasse, die IBackgroundTask in Ihrem App-Dienstprojekt implementiert.

Behandeln von Problemen beim Debuggen

Wenn der Debugger an Haltepunkten in Ihren App-Dienstanbieter- oder App-Dienstprojekten nicht beendet wird, überprüfen Sie Folgendes:

  • Stellen Sie sicher, dass das Projekt des App-Dienstanbieters und das App-Dienstprojekt bereitgestellt werden. Beide müssen bereitgestellt werden, bevor der Client ausgeführt wird. Sie können sie über Visual Studio bereitstellen, indem Sie die 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 dann auf "Debuggen" (oder "Debuggen in C++"). Ändern Sie in C# die Startaktion in "Nicht starten", sondern debuggen Sie meinen Code, wenn sie gestartet wird. Legen Sie in C++ "Anwendung starten" auf "Nein" fest.

Hinweise

Dieses Beispiel enthält eine Einführung in das Erstellen eines App-Diensts, der als Hintergrundaufgabe ausgeführt und von einer anderen App aufgerufen wird. 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-Dienstanbieters hinzu.
  • Rufen Sie den Paketfamiliennamen des App-Dienstanbieters ab, damit wir über die Client-App eine Verbindung damit herstellen können.
  • Fügen Sie dem App-Dienstprojekt einen Projekt-zu-Projektverweis 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();
            }
        }
    }
}