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 verpackten Desktop-Apps unterstützt.

Um zu veranschaulichen, wie eine App-Erweiterung erstellt wird, verwendet dieser Artikel Xml- und Codeausschnitte des Paketmanifests aus dem Codebeispiel für die Mathematische Erweiterung. Dieses Beispiel ist eine UWP-App, aber die im Beispiel gezeigten Features gelten auch für verpackte Desktop-Apps. Führen Sie die folgenden Anweisungen aus, um mit dem Beispiel zu beginnen:

  • Laden Sie das Codebeispiel für die Mathematische Erweiterung herunter, und entpacken Sie es.
  • Öffnen Sie in Visual Studio 2019 MathExtensionSample.sln. Legen Sie den Buildtyp auf x86 fest (Build>Configuration Manager, und ändern Sie dann die 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 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 verpackte Desktop-Apps mit einer Erweiterungsdeklaration, mit der sie Inhalte und Bereitstellungsereignisse für eine Host-App freigeben können. Eine Erweiterungs-App kann mehrere Erweiterungen bereitstellen.

Da App-Erweiterungen nur UWP-Apps oder verpackte Desktop-Apps sind, können sie auch voll funktionsfähige Apps, Hosterweiterungen sein 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 für Ihre App zu entwickeln, in dem andere Entwickler Ihre App so verbessern können, dass Sie die Ressourcen möglicherweise nicht erwartet oder hatten. Erwägen Sie Microsoft Office-Erweiterungen, Visual Studio-Erweiterungen, Browsererweiterungen usw. Diese schaffen eine umfangreichere Benutzererfahrung für apps, die über die funktionalität hinausgehen, mit der sie ausgeliefert wurden. Erweiterungen können Ihrer App Mehrwert und Langlebigkeit hinzufügen.

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

  1. Deklarieren Sie eine App als Erweiterungshost.
  2. Deklarieren Sie eine App als Erweiterung.
  3. Entscheiden Sie, ob die Erweiterung als App-Dienst, 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 Sie das Codebeispiel für 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.

Beispiel für mathematische Erweiterungscode

Deklarieren einer App als Erweiterungshost

Eine App identifiziert sich selbst als App-Erweiterungshost, indem das Element in der <AppExtensionHost> Datei "Package.appxmanifest" deklariert wird. Schauen Sie sich die Datei "Package.appxmanifest " im MathExtensionHost-Projekt an, um zu sehen, wie dies geschieht.

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 die xmlns:uap3="http://..." und die Anwesenheit von uap3 in IgnorableNamespaces. 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 Vertragsname der Erweiterung. Wenn eine Erweiterung denselben Erweiterungsvertragsnamen angibt, kann der Host sie finden. Der Konvention folgend wird empfohlen, den Namen des Erweiterungsvertrags mithilfe Ihres App- oder Herausgebernamens zu erstellen, um potenzielle Konflikte mit anderen Erweiterungsvertragsnamen 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 als App-Erweiterung, indem das Element in der <uap3:AppExtension> Datei "Package.appxmanifest " deklariert wird. Ö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 Zeile xmlns:uap3="http://..." 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 Erweiterungsvertragsname. Wenn er mit dem in einem Host deklarierten Namen übereinstimmt, kann dieser die Erweiterung finden. ✔️
ID Dient zur eindeutigen Identifizierung dieser Erweiterung. Da es mehrere Erweiterungen geben kann, die denselben Erweiterungsvertragsnamen verwenden (denken Sie beispielsweise an eine Paint-App, 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 Erweiterungstyp abzuleiten. Sie könnten beispielsweise eine Erweiterung für Desktop-PCs und eine andere für Mobilgeräte haben, bei der die ID als Unterscheidungsmerkmal dient. Sie könnten dafür auch das weiter unten erläuterte Eigenschaften-Element (Properties) 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 und 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 und 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. Gemäß der Konvention lautet der Name „Public“, Sie können aber auch 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-Dienst implementiert, sodass der Host eine Möglichkeit benötigt, dessen Namen abzurufen, um ihn aufrufen zu können. Der Name des App-Diensts wird im <Service>-Element definiert, das wir definiert haben (wir hätten ihn beliebig benennen 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.

Die Build 2016-Sitzung zu App-Erweiterungen veranschaulicht die Verwendung des öffentlichen Ordners, der zwischen dem Host und den Erweiterungen gemeinsam genutzt 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, einfach zu sein, erfordert keine Kompilierung und kann das Erstellen der standardmäßigen Startseite unterstützen, die Anweisungen für die Erweiterung und einen Link zur Microsoft Store-Seite der Host-App bereitstellt. Ausführliche Informationen finden Sie im Codebeispiel für die Build 2016-App-Erweiterung. Siehe insbesondere das InvertImageExtension-Projekt und InvokeLoad() in ExtensionManager.cs im ExtensibilitySample-Projekt .

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 heruntergestreckt, 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 unterschiedliche Funktionen aufweist als der Host.
  • Es gibt eine Isolation zwischen Daten im Dienst und der Host-App.

Host-App-Dienstcode

Hier ist der Hostcode, der den App-Dienst 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 aufrufenden App-Diensts bestimmt wird. Da der Host keine Informationen zur Implementierung der Erweiterung enthält, muss die Erweiterung den Namen des App-Diensts angeben. Im Codebeispiel deklariert die Erweiterung den Namen des App-Diensts in der 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 aufrufen kann.

Wenn der Host eine Erweiterung lädt, extrahiert Code wie hier 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

Mit dem Namen des im _serviceNameApp-Dienst gespeicherten App-Diensts 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, wie der Host und die Erweiterung kommunizieren

App-Dienste verwenden ein ValueSet zum Austauschen von Informationen. Als Autor des Hosts müssen Sie ein Protokoll für die Kommunikation mit erweiterungen entwickeln, die flexibel sind. 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 Arg1 . B. und Arg2. Der Host übergibt alle Argumente im ValueSet, und die Erweiterung verwendet die benötigten Argumente. Wenn die Erweiterung ein Ergebnis berechnen kann, erwartet der Host, dass das von der Erweiterung zurückgegebene ValueSet einen Schlüssel mit dem Namen Result enthält, 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.

Erweiterungs-App-Dienstcode

Im Codebeispiel wird der App-Dienst der Erweiterung nicht als Hintergrundaufgabe implementiert. Stattdessen wird das einzelne Proc-App-Dienstmodell verwendet, in dem der App-Dienst im selben Prozess ausgeführt wird wie die Erweiterungs-App, die sie hostt. Dies ist immer noch ein anderer Prozess als die Host-App, was 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. Siehe Konvertieren eines App-Diensts für die Ausführung im selben Prozess wie die Host-App , um den Unterschied zwischen einem App-Dienst zu sehen, der als Hintergrundaufgabe ausgeführt wird, im vergleich zu demselben Prozess.

Das System nimmt an OnBackgroundActivate() , wann der App-Dienst aktiviert wird. Dieser Code richtet Ereignishandler ein, um den tatsächlichen App-Dienstaufruf zu behandeln, wenn es um (OnAppServiceRequestReceived()) geht, sowie um Housekeepingereignisse, z. B. das Abrufen eines Verzögerungsobjekts, 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 ausführt, befindet sich in OnAppServiceRequestReceived(). Diese Funktion wird aufgerufen, wenn der App-Dienst aufgerufen wird, um eine Berechnung auszuführen. Er extrahiert die werte, die er aus dem ValueSet benötigt. Wenn die Berechnung ausgeführt werden kann, wird das Ergebnis unter einem Schlüssel namens "Result" im Wertsatz platziert, der an den Host zurückgegeben wird. Erinnern Sie sich daran, dass gemäß dem Protokoll, das definiert ist, wie dieser Host und seine Erweiterungen kommunizieren, das Vorhandensein eines Ergebnisschlüssels auf Erfolg hinweist; andernfalls ein 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 gesehen 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 reagiert auf das Hinzufügen und Entfernen von Paketen, die Erweiterungen enthalten.

Der Microsoft Store stellt Erweiterungen als Pakete bereit. Der AppExtensionCatalog findet installierte Pakete, 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 (in ExtensionManager.cs im MathExtensionHost-Projekt definiert) die Logik zum Laden von Erweiterungen und reagieren auf Erweiterungspaketinstallationen und -deinstallationen.

Der ExtensionManager Konstruktor verwendet die AppExtensionCatalog App-Erweiterungen auf dem System mit demselben Erweiterungsvertragsnamen wie der Host:

ExtensionManager.cs im MathExtensionHost-Projekt.

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

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

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

Um zu sagen, dass die Erweiterung geladen wird (siehe Load() in ExtensionManager.cs), bedeutet, dass der Paketstatus einwandfrei ist und dass wir die ID, das Logo, die Beschreibung und den öffentlichen Ordner erhalten haben (die wir in diesem Beispiel nicht verwenden, um zu zeigen, wie Sie es erhalten). Das Erweiterungspaket selbst wird nicht geladen.

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

Dies ExtensionManager stellt eine Sammlungsinstanz Extension bereit, sodass die Erweiterungen, ihre Namen, Beschreibungen und Logos an die Benutzeroberfläche gebunden werden können. Die ExtensionsTab-Seite bindet an diese Sammlung und stellt ui zum Aktivieren/Deaktivieren von Erweiterungen sowie zum Entfernen bereit.

Beispiel-Benutzeroberfläche der 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 aus der Liste der Erweiterungen entfernt, die für die Host-App verfügbar sind.

Benutzeroberfläche deinstallieren

Debuggen von App-Erweiterungen und Hosts

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

  1. Laden Sie Ihr Hostprojekt in einer Instanz von Visual Studio.
  2. Laden Sie Die Erweiterung in einer anderen Instanz 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, führen Sie zum Testen des Paketinstallationsereignisses des HostsErstellen > Sie stattdessen die Bereitstellungslösung).

Jetzt können Sie haltepunkte auf dem Host und der Erweiterung treffen. Wenn Sie mit dem Debuggen der Erweiterungs-App selbst beginnen, wird ein leeres Fenster für die App angezeigt. Wenn Sie das leere Fenster nicht sehen möchten, können Sie die Debugeinstellungen für das Erweiterungsprojekt ändern, um die App nicht zu starten, sondern sie beim Starten zu debuggen (klicken Sie mit der rechten Maustaste auf das Erweiterungsprojekt, Eigenschaftendebugging>> wählen Sie "Nicht starten" aus, aber debuggen Sie meinen Code beim Start) Sie müssen trotzdem mit dem Debuggen (F5) des Erweiterungsprojekts beginnen, aber es wartet, bis der Host die Erweiterung aktiviert, und dann werden Ihre Haltepunkte in der Erweiterung getroffen.

Debuggen des Codebeispiels

Im Codebeispiel befinden sich der Host und die Erweiterung in derselben Lösung. Gehen Sie wie folgt vor, um das Debuggen auszuführen:

  1. Stellen Sie sicher, dass MathExtensionHost das Startprojekt ist (klicken Sie mit der rechten Maustaste auf das MathExtensionHost-Projekt , klicken Sie auf 'Als Startprojekt festlegen').
  2. Setzen Sie einen Haltepunkt Invoke in ExtensionManager.cs im MathExtensionHost-Projekt ein.
  3. F5 zum Ausführen des MathExtensionHost-Projekts .
  4. Setzen 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), das es bereitstellt und das Paketinstallationsereignis im Host auslöst.
  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 getroffen, und Der Aufruf des App-Diensts für Erweiterungen wird angezeigt. Anschließend wird die OnAppServiceRequestReceived() Methode in der Erweiterung erreicht, und Sie können sehen, dass der App-Dienst das Ergebnis berechnet und zurückgibt.

Problembehandlung für Erweiterungen, die als App-Dienst implementiert wurden

Wenn beim Erweiterungshost Probleme beim Herstellen einer Verbindung mit dem App-Dienst für Die Erweiterung auftreten, stellen Sie sicher, dass das <uap:AppService Name="..."> Attribut mit dem <Service> Element übereinstimmt. Wenn sie nicht übereinstimmen, stimmt der Dienstname, den Ihre Erweiterung bereitstellt, nicht mit dem app-Dienstnamen ü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 von grundlegenden Szenarien zum Testen

Wenn Sie einen Erweiterungshost erstellen und bereit sind, zu testen, wie gut erweiterungen unterstützt werden, sind hier einige grundlegende Szenarien, die Sie ausprobieren können:

  • Führen Sie den Host aus, und stellen Sie dann eine Erweiterungs-App bereit.
    • Nimmt der Host während der Ausführung neue Erweiterungen auf?
  • Stellen Sie die Erweiterungs-App bereit, und stellen Sie den Host bereit, und führen Sie sie aus.
    • Nimmt der Host bereits vorhandene Erweiterungen auf?
  • Führen Sie den Host aus, und entfernen Sie dann die Erweiterungs-App.
    • Erkennt der Host die Entfernung ordnungsgemäß?
  • Führen Sie den Host aus, und aktualisieren Sie dann die Erweiterungs-App auf eine neuere Version.
    • Nimmt der Host die Änderung auf 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 Paketstatus und deaktiviert die Erweiterung?
  • Führen Sie den Host aus, und beschädigt Sie dann die Erweiterungs-App (machen Sie sie 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 mit ungültigen Inhalten oder Eigenschaften bereit.
    • Erkennt der Host ungültige Inhalte und behandelt ihn ordnungsgemäß?

Überlegungen zum Entwurf

  • Stellen Sie eine Benutzeroberfläche bereit, die dem Benutzer anzeigt, welche Erweiterungen verfügbar sind, und ermöglicht es ihnen, sie zu aktivieren/zu deaktivieren. Möglicherweise können Sie auch Glyphen für Erweiterungen hinzufügen, die nicht verfügbar werden, da ein Paket offline geht usw.
  • Leiten Sie den Benutzer an die Stelle, an der er Erweiterungen erhalten kann. Möglicherweise kann Ihre Erweiterungsseite eine Microsoft Store-Suchabfrage bereitstellen, die eine Liste der Erweiterungen anzeigt, die mit Ihrer App verwendet werden können.
  • Überlegen Sie, wie Sie den Benutzer über das Hinzufügen und Entfernen von Erweiterungen informieren. Möglicherweise erstellen Sie eine Benachrichtigung darüber, wann eine neue Erweiterung installiert ist, und laden Sie den Benutzer ein, sie zu aktivieren. Erweiterungen sollten standardmäßig deaktiviert werden, damit Benutzer die Kontrolle behalten.

Unterschiede zwischen App-Erweiterungen und optionalen Paketen

Der schlüsselunterschiedliche Unterschied zwischen optionalen Paketen und App-Erweiterungen ist ein offenes Ökosystem im Vergleich zum geschlossenen Ökosystem und abhängiges Paket im Vergleich zu unabhängigen Paketen.

App-Erweiterungen nehmen an einem offenen Ökosystem teil. Wenn Ihre App App-Erweiterungen hosten kann, kann jeder eine Erweiterung für Ihren Host schreiben, solange sie Ihre Methode zum Übergeben/Empfangen von Informationen aus der Erweiterung einhalten. 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 kann nicht unabhängig vom Spiel ausgeführt werden, und Sie möchten möglicherweise nicht, dass Erweiterungspakete nur von jedem Entwickler im Ökosystem erstellt werden.

Wenn dasselbe Spiel anpassbare UI-Add-Ons oder Designs hatte, kann eine App-Erweiterung eine gute Wahl sein, da die App, die die Erweiterung bereitstellt, eigenständig ausgeführt werden kann und jeder Drittanbieter sie erstellen könnte.

Hinweise

Dieses Thema enthält eine Einführung in App-Erweiterungen. Die wichtigsten Punkte, die Sie beachten müssen, sind die Erstellung des Hosts und das Markieren als solche in der Datei "Package.appxmanifest", das Erstellen der Erweiterung und das Markieren als solche in der Datei "Package.appxmanifest", bestimmen, wie die Erweiterung implementiert werden soll (z. B. ein App-Dienst, Hintergrundaufgabe oder andere Mittel), definieren, wie der Host mit Erweiterungen kommuniziert, und verwenden Sie die AppExtensions-API , um auf Erweiterungen zuzugreifen und sie zu verwalten.