Erstellen und Hosten einer App-Erweiterung

In diesem Artikel erfahren Sie, wie Sie eine Windows 10 App-Erweiterung erstellen und in einer App hosten. App-Erweiterungen werden in UWP-Apps und gepackten Desktop-Apps unterstützt.

Um zu veranschaulichen, wie eine App-Erweiterung erstellt wird, verwendet dieser Artikel XML-Paketmanifest-XML und Codeausschnitte aus dem Codebeispiel der Math-Erweiterung. Dieses Beispiel ist eine UWP-App, aber die im Beispiel gezeigten Features gelten auch für gepackte Desktop-Apps. Befolgen Sie die folgenden Anweisungen, um mit dem Beispiel zu beginnen:

  • Laden Sie das Codebeispiel mathematische Erweiterung herunter, und entpacken Sie es.
  • Öffnen Sie in Visual Studio 2019 MathExtensionSample.sln. Legen Sie den Buildtyp auf x86 (Build>Configuration Manager fest, und ändern Sie plattform für beide Projekte in x86.
  • Bereitstellen der Lösung: Erstellen>der Bereitstellungslösung.

Einführung in App-Erweiterungen

In Windows 10 bieten App-Erweiterungen Ähnliche Funktionen wie Plug-Ins, Add-Ins und Add-Ons auf anderen Plattformen. App-Erweiterungen wurden in der Windows 10 Anniversary-Edition (Version 1607, Build 10.0.14393) eingeführt.

App-Erweiterungen sind UWP-Apps oder gepackte Desktop-Apps, die über eine Erweiterungsdeklaration verfügen, die es ihnen ermöglicht, Inhalte und Bereitstellungsereignisse mit einer Host-App zu teilen. Eine Erweiterungs-App kann mehrere Erweiterungen bereitstellen.

Da App-Erweiterungen nur UWP-Apps oder gepackte Desktop-Apps sind, können sie auch voll funktionsfähige Apps sein, Erweiterungen hosten und Erweiterungen für andere Apps bereitstellen – alles, ohne separate App-Pakete zu erstellen.

Wenn Sie einen App-Erweiterungshost erstellen, erstellen Sie die Möglichkeit, ein Ökosystem rund um Ihre App zu entwickeln, in dem andere Entwickler Ihre App auf eine Weise verbessern können, die Sie möglicherweise nicht erwartet oder nicht über die Ressourcen verfügen. Betrachten Sie Microsoft Office-Erweiterungen, Visual Studio-Erweiterungen, Browsererweiterungen usw. Diese bieten umfassendere Funktionen für apps, die über die funktionen hinausgehen, mit denen sie ausgeliefert wurden. Erweiterungen können Ihrer App Einen Mehrwert und Langlebigkeit verleihen.

Um eine App-Erweiterungsbeziehung einzurichten, müssen wir auf hoher Ebene Folgendes ausführen:

  1. Deklarieren Sie eine App als Erweiterungshost.
  2. Deklarieren Sie eine App als Erweiterung.
  3. Entscheiden Sie, ob die Erweiterung als App Service, Hintergrundaufgabe oder auf andere Weise implementiert werden soll.
  4. Definieren Sie, wie die Hosts und ihre Erweiterungen kommunizieren.
  5. Verwenden Sie die Windows.ApplicationModel.AppExtensions-API in der Host-App, um auf die Erweiterungen zuzugreifen.

Sehen wir uns an, wie dies geschieht, indem wir das Codebeispiel für die Mathematische Erweiterung untersuchen, das einen hypothetischen Rechner implementiert, dem Sie mithilfe von Erweiterungen neue Funktionen hinzufügen können. Laden Sie in Microsoft Visual Studio 2019 MathExtensionSample.sln aus dem Codebeispiel.

Codebeispiel für die Math-Erweiterung

Deklarieren einer App als Erweiterungshost

Eine App identifiziert sich selbst als App-Erweiterungshost, indem sie das Element in der <AppExtensionHost> Datei Package.appxmanifest deklariert. Informationen dazu finden Sie in der Datei Package.appxmanifest im MathExtensionHost-Projekt .

Package.appxmanifest im MathExtensionHost-Projekt

<Package
  ...
  xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
  IgnorableNamespaces="uap uap3 mp">
  ...
    <Applications>
      <Application Id="App" ... >
        ...
        <Extensions>
            <uap3:Extension Category="windows.appExtensionHost">
                <uap3:AppExtensionHost>
                  <uap3:Name>com.microsoft.mathext</uap3:Name>
                </uap3:AppExtensionHost>
          </uap3:Extension>
        </Extensions>
      </Application>
    </Applications>
    ...
</Package>

Beachten Sie, dass xmlns:uap3="http://..." und in IgnorableNamespacesvorhanden uap3 sind. Diese sind erforderlich, da wir den uap3-Namespace verwenden.

<uap3:Extension Category="windows.appExtensionHost"> identifiziert diese App als Erweiterungshost.

Das Name-Element in <uap3:AppExtensionHost> ist der Name des Erweiterungsvertrags . Wenn eine Erweiterung denselben Erweiterungsvertragsnamen angibt, kann der Host ihn finden. Gemäß der Konvention wird empfohlen, den Namen des Erweiterungsvertrags mithilfe Ihres App- oder Herausgebernamens zu erstellen, um potenzielle Konflikte mit anderen Namen von Erweiterungsvertragen zu vermeiden.

Sie können mehrere Hosts und mehrere Erweiterungen in derselben App definieren. In diesem Beispiel deklarieren wir einen Host. Die Erweiterung ist in einer anderen App definiert.

Deklarieren einer App als Erweiterung

Eine App identifiziert sich selbst als App-Erweiterung, indem sie das Element in der <uap3:AppExtension>Datei Package.appxmanifest deklariert. Öffnen Sie die Datei Package.appxmanifest im MathExtension-Projekt , um zu sehen, wie dies geschieht.

Package.appxmanifest im MathExtension-Projekt:

<Package
  ...
  xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
  IgnorableNamespaces="uap uap3 mp">
  ...
    <Applications>
      <Application Id="App" ... >
        ...
        <Extensions>
          ...
          <uap3:Extension Category="windows.appExtension">
            <uap3:AppExtension Name="com.microsoft.mathext"
                               Id="power"
                               DisplayName="x^y"
                               Description="Exponent"
                               PublicFolder="Public">
              <uap3:Properties>
                <Service>com.microsoft.powservice</Service>
              </uap3:Properties>
              </uap3:AppExtension>
          </uap3:Extension>
        </Extensions>
      </Application>
    </Applications>
    ...
</Package>

Beachten Sie erneut die xmlns:uap3="http://..." Zeile und das Vorhandensein von uap3 in IgnorableNamespaces. Diese sind erforderlich, da wir den uap3 Namespace verwenden.

<uap3:Extension Category="windows.appExtension"> identifiziert diese App als Erweiterung.

Die Bedeutung der <uap3:AppExtension> Attribute lautet wie folgt:

attribute BESCHREIBUNG Erforderlich
Name Dies ist der Name des Erweiterungsvertrags. Wenn er mit dem in einem Host deklarierten Namen übereinstimmt, kann dieser Host diese Erweiterung finden. ✔️
ID Identifiziert diese Erweiterung eindeutig. Da es mehrere Erweiterungen geben kann, die denselben Erweiterungsvertragsnamen verwenden (stellen Sie sich eine Paint-App vor, die mehrere Erweiterungen unterstützt), können Sie die ID verwenden, um sie voneinander zu unterscheiden. App-Erweiterungshosts können die ID verwenden, um etwas über den Typ der Erweiterung abzuleiten. Beispielsweise könnten Sie eine Erweiterung für Desktop und eine andere für Mobilgeräte haben, wobei die ID das Unterscheidungsmerkzeichen ist. Sie können dazu auch das Unten erläuterte Properties-Element verwenden. ✔️
DisplayName Kann von Ihrer Host-App verwendet werden, um die Erweiterung für den Benutzer zu identifizieren. Es kann über das neue Ressourcenverwaltungssystem (ms-resource:TokenName) abfragt werden und kann für die Lokalisierung verwendet werden. Der lokalisierte Inhalt wird aus dem App-Erweiterungspaket geladen, nicht aus der Host-App.
Beschreibung Kann von Ihrer Host-App verwendet werden, um die Erweiterung für den Benutzer zu beschreiben. Es kann über das neue Ressourcenverwaltungssystem (ms-resource:TokenName) abfragt werden und kann für die Lokalisierung verwendet werden. Der lokalisierte Inhalt wird aus dem App-Erweiterungspaket geladen, nicht aus der Host-App.
PublicFolder Der Name eines Ordners relativ zum Paketstamm, in dem Sie Inhalte für den Erweiterungshost freigeben können. Standardmäßig lautet der Name "Public", aber Sie können einen beliebigen Namen verwenden, der mit einem Ordner in Ihrer Erweiterung übereinstimmt. ✔️

<uap3:Properties> ist ein optionales Element, das benutzerdefinierte Metadaten enthält, die Hosts zur Laufzeit lesen können. Im Codebeispiel wird die Erweiterung als App Service implementiert, sodass der Host eine Möglichkeit benötigt, den Namen dieses App-Diensts abzurufen, damit er ihn aufrufen kann. Der Name des App-Diensts wird im <Service-Element> definiert, das wir definiert haben (wir hätten ihn beliebig nennen können). Der Host im Codebeispiel sucht zur Laufzeit nach dieser Eigenschaft, um den Namen des App-Diensts zu erfahren.

Entscheiden Sie, wie Sie die Erweiterung implementieren möchten.

Die Build 2016-Sitzung zu App-Erweiterungen veranschaulicht die Verwendung des öffentlichen Ordners, der zwischen dem Host und den Erweiterungen freigegeben wird. In diesem Beispiel wird die Erweiterung von einer JavaScript-Datei implementiert, die im öffentlichen Ordner gespeichert ist, den der Host aufruft. Dieser Ansatz hat den Vorteil, dass er einfach ist, keine Kompilierung erfordert und die Erstellung der Standardzielseite unterstützen kann, die Anweisungen für die Erweiterung und einen Link zur Microsoft Store-Seite der Host-App enthält. Weitere Informationen finden Sie im Codebeispiel für die Build 2016-App-Erweiterung . Sehen Sie sich insbesondere das Projekt InvertImageExtension und InvokeLoad() in ExtensionManager.cs im Projekt ExtensibilitySample an.

In diesem Beispiel verwenden wir einen App-Dienst, um die Erweiterung zu implementieren. App-Dienste haben die folgenden Vorteile:

  • Wenn die Erweiterung abstürzt, wird die Host-App nicht heruntergefahren, da die Host-App in einem eigenen Prozess ausgeführt wird.
  • Sie können die Sprache Ihrer Wahl verwenden, um den Dienst zu implementieren. Es muss nicht mit der Sprache übereinstimmen, die zum Implementieren der Host-App verwendet wird.
  • Der App-Dienst hat Zugriff auf einen eigenen App-Container, der möglicherweise andere Funktionen als der Host hat.
  • Es gibt eine Isolation zwischen Daten im Dienst und der Host-App.

Hosten von App Service-Code

Hier sehen Sie den Hostcode, der den App Service der Erweiterung aufruft:

ExtensionManager.cs im MathExtensionHost-Projekt

public async Task<double> Invoke(ValueSet message)
{
    if (Loaded)
    {
        try
        {
            // make the app service call
            using (var connection = new AppServiceConnection())
            {
                // service name is defined in appxmanifest properties
                connection.AppServiceName = _serviceName;
                // package Family Name is provided by the extension
                connection.PackageFamilyName = AppExtension.Package.Id.FamilyName;

                // open the app service connection
                AppServiceConnectionStatus status = await connection.OpenAsync();
                if (status != AppServiceConnectionStatus.Success)
                {
                    Debug.WriteLine("Failed App Service Connection");
                }
                else
                {
                    // Call the app service
                    AppServiceResponse response = await connection.SendMessageAsync(message);
                    if (response.Status == AppServiceResponseStatus.Success)
                    {
                        ValueSet answer = response.Message as ValueSet;
                        if (answer.ContainsKey("Result")) // When our app service returns "Result", it means it succeeded
                        {
                            return (double)answer["Result"];
                        }
                    }
                }
            }
        }
        catch (Exception)
        {
             Debug.WriteLine("Calling the App Service failed");
        }
    }
    return double.NaN; // indicates an error from the app service
}

Dies ist typischer Code zum Aufrufen eines App-Diensts. Ausführliche Informationen zum Implementieren und Aufrufen eines App-Diensts finden Sie unter Erstellen und Nutzen eines App-Diensts.

Beachten Sie, wie der Name des aufzurufenden App-Diensts bestimmt wird. Da der Host über keine Informationen zur Implementierung der Erweiterung verfügt, muss die Erweiterung den Namen ihres App-Diensts angeben. Im Codebeispiel deklariert die Erweiterung den Namen des App-Diensts in seiner Datei im <uap3:Properties> -Element:

Package.appxmanifest im MathExtension-Projekt

    ...
    <uap3:Extension Category="windows.appExtension">
      <uap3:AppExtension ...>
        <uap3:Properties>
          <Service>com.microsoft.powservice</Service>
        </uap3:Properties>
        </uap3:AppExtension>
    </uap3:Extension>

Sie können ihre eigene XML-Datei im <uap3:Properties> -Element definieren. In diesem Fall definieren wir den Namen des App-Diensts, damit der Host die Erweiterung aufruft.

Wenn der Host eine Erweiterung lädt, extrahiert Code wie dieser den Namen des Diensts aus den Eigenschaften, die im Package.appxmanifest der Erweiterung definiert sind:

Update() in ExtensionManager.cs, im MathExtensionHost-Projekt

...
var properties = await ext.GetExtensionPropertiesAsync() as PropertySet;

...
#region Update Properties
// update app service information
_serviceName = null;
if (_properties != null)
{
   if (_properties.ContainsKey("Service"))
   {
       PropertySet serviceProperty = _properties["Service"] as PropertySet;
       this._serviceName = serviceProperty["#text"].ToString();
   }
}
#endregion

Da der Name des App-Diensts in _serviceNamegespeichert ist, kann der Host ihn verwenden, um den App-Dienst aufzurufen.

Das Aufrufen eines App-Diensts erfordert auch den Familiennamen des Pakets, das den App-Dienst enthält. Glücklicherweise stellt die App-Erweiterungs-API diese Informationen bereit, die in der Zeile abgerufen werden: connection.PackageFamilyName = AppExtension.Package.Id.FamilyName;

Definieren der Kommunikation zwischen Host und Erweiterung

App-Dienste verwenden ValueSet zum Austauschen von Informationen. Als Autor des Hosts müssen Sie ein flexibles Protokoll für die Kommunikation mit Erweiterungen erstellen. Im Codebeispiel bedeutet dies, dass Erweiterungen berücksichtigt werden, die in Zukunft 1, 2 oder mehr Argumente annehmen können.

In diesem Beispiel ist das Protokoll für die Argumente ein ValueSet , das die Schlüsselwertpaare mit dem Namen "Arg" + der Argumentnummer enthält, z. B Arg1 . und Arg2. Der Host übergibt alle Argumente im ValueSet, und die Erweiterung verwendet die argumente, die sie benötigt. Wenn die Erweiterung ein Ergebnis berechnen kann, erwartet der Host, dass das von der Erweiterung zurückgegebene ValueSet über einen Schlüssel namens verfügt Result , der den Wert der Berechnung enthält. Wenn dieser Schlüssel nicht vorhanden ist, geht der Host davon aus, dass die Erweiterung die Berechnung nicht abschließen konnte.

App Service-Code der Erweiterung

Im Codebeispiel wird der App Service der Erweiterung nicht als Hintergrundaufgabe implementiert. Stattdessen wird das einzelne Proc App Service-Modell verwendet, bei dem der App-Dienst im selben Prozess wie die Erweiterungs-App ausgeführt wird, die ihn hostet. Dies ist immer noch ein anderer Prozess als die Host-App, der die Vorteile der Prozesstrennung bietet, während einige Leistungsvorteile erzielt werden, indem die prozessübergreifende Kommunikation zwischen dem Erweiterungsprozess und dem Hintergrundprozess vermieden wird, der den App-Dienst implementiert. Informationen zum Unterschied zwischen einem App-Dienst, der als Hintergrundaufgabe ausgeführt wird, finden Sie unter Konvertieren eines App-Diensts, der im selben Prozess ausgeführt wird.

Das System stellt ein, OnBackgroundActivate() wenn der App-Dienst aktiviert wird. Dieser Code richtet Ereignishandler ein, um den tatsächlichen App Service-Aufruf zu behandeln, wenn er kommt (OnAppServiceRequestReceived()), sowie housekeeping-Ereignisse zu behandeln, z. B. das Abrufen eines Zurückstellungsobjekts, das ein Abbruch- oder geschlossenes Ereignis behandelt.

App.xaml.cs im MathExtension-Projekt.

protected override void OnBackgroundActivated(BackgroundActivatedEventArgs args)
{
    base.OnBackgroundActivated(args);

    if ( _appServiceInitialized == false ) // Only need to setup the handlers once
    {
        _appServiceInitialized = true;

        IBackgroundTaskInstance taskInstance = args.TaskInstance;
        taskInstance.Canceled += OnAppServicesCanceled;

        AppServiceTriggerDetails appService = taskInstance.TriggerDetails as AppServiceTriggerDetails;
        _appServiceDeferral = taskInstance.GetDeferral();
        _appServiceConnection = appService.AppServiceConnection;
        _appServiceConnection.RequestReceived += OnAppServiceRequestReceived;
        _appServiceConnection.ServiceClosed += AppServiceConnection_ServiceClosed;
    }
}

Der Code, der die Arbeit der Erweiterung übernimmt, befindet sich in OnAppServiceRequestReceived(). Diese Funktion wird aufgerufen, wenn der App-Dienst aufgerufen wird, um eine Berechnung durchzuführen. Es extrahiert die benötigten Werte aus dem ValueSet. Wenn die Berechnung möglich ist, wird das Ergebnis unter einem Schlüssel mit dem Namen Result im ValueSet platziert, das an den Host zurückgegeben wird. Erinnern Sie sich daran, dass gemäß dem Protokoll, das für die Kommunikation dieses Hosts und seiner Erweiterungen definiert ist, das Vorhandensein eines Ergebnisschlüssels den Erfolg anzeigt; andernfalls fehler.

App.xaml.cs im MathExtension-Projekt.

private async void OnAppServiceRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
{
    // Get a deferral because we use an awaitable API below (SendResponseAsync()) to respond to the message
    // and we don't want this call to get cancelled while we are waiting.
    AppServiceDeferral messageDeferral = args.GetDeferral();
    ValueSet message = args.Request.Message;
    ValueSet returnMessage = new ValueSet();

    double? arg1 = Convert.ToDouble(message["arg1"]);
    double? arg2 = Convert.ToDouble(message["arg2"]);
    if (arg1.HasValue && arg2.HasValue)
    {
        returnMessage.Add("Result", Math.Pow(arg1.Value, arg2.Value)); // For this sample, the presence of a "Result" key will mean the call succeeded
    }

    await args.Request.SendResponseAsync(returnMessage);
    messageDeferral.Complete();
}

Verwalten von Erweiterungen

Nachdem wir nun erfahren haben, wie die Beziehung zwischen einem Host und seinen Erweiterungen implementiert wird, sehen wir uns an, wie ein Host erweiterungen findet, die auf dem System installiert sind und auf das Hinzufügen und Entfernen von Paketen mit Erweiterungen reagiert.

Der Microsoft Store stellt Erweiterungen als Pakete bereit. AppExtensionCatalog sucht nach installierten Paketen, die Erweiterungen enthalten, die dem Namen des Erweiterungsvertrags des Hosts entsprechen, und stellt Ereignisse bereit, die ausgelöst werden, wenn ein für den Host relevantes App-Erweiterungspaket installiert oder entfernt wird.

Im Codebeispiel umschließt die ExtensionManager -Klasse (definiert in ExtensionManager.cs im MathExtensionHost-Projekt ) die Logik zum Laden von Erweiterungen und zum Reagieren auf Installation und Deinstallationen von Erweiterungspaketen.

Der ExtensionManager Konstruktor verwendet, AppExtensionCatalog um die App-Erweiterungen auf dem System zu suchen, die denselben Erweiterungsvertragsnamen wie der Host haben:

ExtensionManager.cs im MathExtensionHost-Projekt.

public ExtensionManager(string extensionContractName)
{
   // catalog & contract
   ExtensionContractName = extensionContractName;
   _catalog = AppExtensionCatalog.Open(ExtensionContractName);
   ...
}

Wenn ein Erweiterungspaket installiert wird, ExtensionManager werden Informationen zu den Erweiterungen im Paket gesammelt, die denselben Erweiterungsvertragsnamen wie der Host haben. Eine Installation kann ein Update darstellen, in dem die Informationen der betroffenen Erweiterung aktualisiert werden. Wenn ein Erweiterungspaket deinstalliert wird, ExtensionManager werden Informationen zu den betroffenen Erweiterungen entfernt, damit der Benutzer weiß, welche Erweiterungen nicht mehr verfügbar sind.

Die Extension -Klasse (definiert in ExtensionManager.cs im MathExtensionHost-Projekt ) wurde für das Codebeispiel erstellt, um auf die ID, beschreibung, das Logo und appspezifische Informationen einer Erweiterung zuzugreifen, z. B. ob der Benutzer die Erweiterung aktiviert hat.

Wenn Sie sagen möchten, dass die Erweiterung geladen ist (siehe Load()ExtensionManager.cs), bedeutet dies, dass das Paket status in Ordnung ist und dass wir die ID, das Logo, die Beschreibung und den öffentlichen Ordner abgerufen haben (die wir in diesem Beispiel nicht verwenden, nur um zu zeigen, wie Sie es erhalten). Das Erweiterungspaket selbst wird nicht geladen.

Das Konzept des Entladens wird verwendet, um nachzuverfolgen, welche Erweiterungen dem Benutzer nicht mehr präsentiert werden sollen.

Stellt ExtensionManager eine Sammlungsinstanz Extension bereit, sodass die Erweiterungen, deren Namen, Beschreibungen und Logos an die Benutzeroberfläche gebunden werden können. Die Registerkarte "Erweiterungen" ist an diese Sammlung gebunden und stellt eine Benutzeroberfläche zum Aktivieren/Deaktivieren von Erweiterungen sowie zum Entfernen von Erweiterungen bereit.

Beispiel für die Registerkarte

Wenn eine Erweiterung entfernt wird, fordert das System den Benutzer auf, zu überprüfen, ob er das Paket deinstallieren möchte, das die Erweiterung enthält (und möglicherweise andere Erweiterungen enthält). Wenn der Benutzer zustimmt, wird das Paket deinstalliert, und die ExtensionManager Erweiterungen im deinstallierten Paket werden aus der Liste der Erweiterungen entfernt, die für die Host-App verfügbar sind.

Deinstallieren der Benutzeroberfläche

Debuggen von App-Erweiterungen und Hosts

Häufig sind der Erweiterungshost und die Erweiterung nicht Teil derselben Lösung. So debuggen Sie in diesem Fall den Host und die Erweiterung:

  1. Laden Sie Ihr Hostprojekt in eine instance von Visual Studio.
  2. Laden Sie Ihre Erweiterung in eine andere instance von Visual Studio.
  3. Starten Sie Ihre Host-App im Debugger.
  4. Starten Sie die Erweiterungs-App im Debugger. (Wenn Sie die Erweiterung bereitstellen möchten, anstatt sie zu debuggen, um das Paketinstallationsereignis des Hosts zu testen, führen Sie stattdessen Build > Deploy Solution aus.)

Jetzt können Sie Breakpoints im Host und in der Erweiterung erreichen. Wenn Sie mit dem Debuggen der Erweiterungs-App selbst beginnen, wird ein leeres Fenster für die App angezeigt. Wenn Das leere Fenster nicht angezeigt werden soll, können Sie die Debugeinstellungen für das Erweiterungsprojekt ändern, um die App nicht zu starten, sondern stattdessen beim Starten zu debuggen (klicken Sie mit der rechten Maustaste auf das Erweiterungsprojekt, Eigenschaften>Debuggen> wählen Sie Nicht starten, sondern debuggen meinen Code aus, wenn es gestartet wird). Sie müssen weiterhin mit dem Debuggen des Erweiterungsprojekts beginnen (F5) des Erweiterungsprojekts. Es wird jedoch gewartet, bis der Host die Erweiterung aktiviert, und dann werden Ihre Haltepunkte in der Erweiterung erreicht.

Debuggen des Codebeispiels

Im Codebeispiel befinden sich der Host und die Erweiterung in derselben Projektmappe. Führen Sie zum Debuggen die folgenden Schritte aus:

  1. Stellen Sie sicher, dass MathExtensionHost das Startprojekt ist (klicken Sie mit der rechten Maustaste auf das MathExtensionHost-Projekt , und klicken Sie auf Als Startprojekt festlegen).
  2. Setzen Sie einen Haltepunkt Invoke in ExtensionManager.cs im MathExtensionHost-Projekt .
  3. F5 , um das MathExtensionHost-Projekt auszuführen.
  4. Legen Sie einen Haltepunkt OnAppServiceRequestReceived in App.xaml.cs im MathExtension-Projekt ein.
  5. Starten Sie das Debuggen des MathExtension-Projekts (klicken Sie mit der rechten Maustaste auf das MathExtension-Projekt, Debug > Start new instance), wodurch es bereitgestellt und das Paketinstallationsereignis auf dem Host ausgelöst wird.
  6. Navigieren Sie in der MathExtensionHost-App zur Seite Berechnung , und klicken Sie auf x^y , um die Erweiterung zu aktivieren. Der Invoke() Haltepunkt wird zuerst erreicht, und Sie können sehen, dass der App-Dienstaufruf der Erweiterungen erfolgt. Dann wird die OnAppServiceRequestReceived() -Methode in der Erweiterung getroffen, und Sie können sehen, wie der App-Dienst das Ergebnis berechnet und zurückgibt.

Problembehandlung bei Erweiterungen, die als App Service implementiert wurden

Wenn ihr Erweiterungshost Probleme beim Herstellen einer Verbindung mit dem App-Dienst für Ihre Erweiterung hat, stellen Sie sicher, dass das Attribut mit dem <uap:AppService Name="..."> übereinstimmt, was Sie in Ihrem <Service> Element eingefügt haben. Wenn sie nicht übereinstimmen, stimmt der Dienstname, den Ihre Erweiterung für den Host bereitstellt, nicht mit dem App Service-Namen überein, den Sie implementiert haben, und der Host kann Ihre Erweiterung nicht aktivieren.

Package.appxmanifest im MathExtension-Projekt:

<Extensions>
   <uap:Extension Category="windows.appService">
     <uap:AppService Name="com.microsoft.sqrtservice" />      <!-- This must match the contents of <Service>...</Service> -->
   </uap:Extension>
   <uap3:Extension Category="windows.appExtension">
     <uap3:AppExtension Name="com.microsoft.mathext" Id="sqrt" DisplayName="Sqrt(x)" Description="Square root" PublicFolder="Public">
       <uap3:Properties>
         <Service>com.microsoft.powservice</Service>   <!-- this must match <uap:AppService Name=...> -->
       </uap3:Properties>
     </uap3:AppExtension>
   </uap3:Extension>
</Extensions>   

Eine Checkliste mit grundlegenden Szenarien, die getestet werden sollen

Wenn Sie einen Erweiterungshost erstellen und testen möchten, wie gut Er Erweiterungen unterstützt, finden Sie hier einige grundlegende Szenarien, die Sie ausprobieren können:

  • Führen Sie den Host aus, und stellen Sie dann eine Erweiterungs-App bereit.
    • Übernimmt der Host neue Erweiterungen, die während der Ausführung kommen?
  • Stellen Sie die Erweiterungs-App bereit, und stellen Sie dann den Host bereit, und führen Sie den Host aus.
    • Übernimmt der Host bereits vorhandene Erweiterungen?
  • Führen Sie den Host aus, und entfernen Sie dann die Erweiterungs-App.
    • Erkennt der Host die Entfernung richtig?
  • Führen Sie den Host aus, und aktualisieren Sie dann die Erweiterungs-App auf eine neuere Version.
    • Übernimmt der Host die Änderung und entlädt die alten Versionen der Erweiterung ordnungsgemäß?

Erweiterte Szenarien zum Testen:

  • Führen Sie den Host aus, verschieben Sie die Erweiterungs-App auf Wechselmedien, entfernen Sie die Medien.
    • Erkennt der Host die Änderung im Paket status und deaktiviert die Erweiterung?
  • Führen Sie den Host aus, und beschädigen Sie dann die Erweiterungs-App (ungültig, anders signiert usw.)
    • Erkennt der Host die manipulierte Erweiterung und behandelt sie ordnungsgemäß?
  • Führen Sie den Host aus, und stellen Sie dann eine Erweiterungs-App bereit, die über ungültige Inhalte oder Eigenschaften verfügt.
    • Erkennt der Host ungültige Inhalte und behandelt ihn ordnungsgemäß?

Überlegungen zum Entwurf

  • Stellen Sie eine Benutzeroberfläche bereit, die dem Benutzer zeigt, welche Erweiterungen verfügbar sind, und ermöglicht es dem Benutzer, diese zu aktivieren/zu deaktivieren. Sie können auch erwägen, Glyphen für Erweiterungen hinzuzufügen, die nicht mehr verfügbar sind, weil ein Paket offline geschaltet wird usw.
  • Leiten Sie den Benutzer dorthin, wo er Erweiterungen abrufen kann. Möglicherweise kann Ihre Erweiterungsseite eine Microsoft Store-Suchabfrage bereitstellen, die eine Liste von Erweiterungen anzeigt, die mit Ihrer App verwendet werden können.
  • Überlegen Sie, wie Sie den Benutzer über das Hinzufügen und Entfernen von Erweiterungen benachrichtigen. Sie können eine Benachrichtigung für die Installation einer neuen Erweiterung erstellen und den Benutzer einladen, sie zu aktivieren. Erweiterungen sollten standardmäßig deaktiviert sein, damit Benutzer die Kontrolle haben.

Unterschiede von App-Erweiterungen und optionalen Paketen

Das wichtigste Unterscheidungsmerkzeichen zwischen optionalen Paketen und App-Erweiterungen sind offenes Ökosystem im Vergleich zu einem geschlossenen Ökosystem sowie abhängiges Paket und unabhängiges Paket.

App-Erweiterungen sind an einem offenen Ökosystem beteiligt. Wenn Ihre App App-Erweiterungen hosten kann, kann jeder eine Erweiterung für Ihren Host schreiben, solange sie Ihrer Methode zum Übergeben/Empfangen von Informationen aus der Erweiterung entsprechen. Dies unterscheidet sich von optionalen Paketen, die an einem geschlossenen Ökosystem teilnehmen, in dem der Herausgeber entscheidet, wer ein optionales Paket erstellen darf, das mit der App verwendet werden kann.

App-Erweiterungen sind unabhängige Pakete und können eigenständige Apps sein. Sie können keine Bereitstellungsabhängigkeit von einer anderen App haben. Bei optionalen Paketen ist das primäre Paket erforderlich und sie können nicht ohne es ausgeführt werden.

Ein Erweiterungspaket für ein Spiel wäre ein guter Kandidat für ein optionales Paket, da es eng an das Spiel gebunden ist, es nicht unabhängig vom Spiel ausgeführt werden kann und Sie möglicherweise nicht möchten, dass Erweiterungspakete nur von jedem Entwickler im Ökosystem erstellt werden.

Wenn dasselbe Spiel anpassbare Ui-Add-Ons oder Themen hatte, könnte eine App-Erweiterung eine gute Wahl sein, da die App, die die Erweiterung bereitstellt, selbst ausgeführt werden kann, und jede dritte Partei sie erstellen könnte.

Hinweise

Dieses Thema enthält eine Einführung in App-Erweiterungen. Die wichtigsten Punkte sind die Erstellung des Hosts und das Markieren als solcher in der Datei Package.appxmanifest, das Erstellen der Erweiterung und das Markieren als solche in der Datei Package.appxmanifest, das Festlegen der Implementierung der Erweiterung (z. B. einen App-Dienst, eine Hintergrundaufgabe oder andere Mittel), die Definition, wie der Host mit Erweiterungen kommuniziert, und verwenden Sie die AppExtensions-API , um auf Erweiterungen zuzugreifen und diese zu verwalten.