Uw app uitbreiden met services, extensies en pakketten

Windows biedt verschillende technologieën waarmee uw app functionaliteit kan bieden aan andere apps of invoegtoepassingen van derden kan gebruiken. In dit artikel worden de beschikbare uitbreidbaarheidsopties voor Windows App SDK desktop-apps vergeleken.

Overzicht van uitbreidbaarheidsopties

Technologie Description Pakketidentiteit vereist Minimaal besturingssysteem
App-services Communicatie tussen apps aanvragen/antwoorden via AppServiceConnection Yes Windows 10 1607
App-extensies Invoegtoepassingsmodel: host-app detecteert inhoud van extensiepakketten Yes Windows 10 1607
Pakketuitbreidingen Bredere uitbreidbaarheid op pakketniveau met uap17:PackageExtension Yes Windows 11
Optionele pakketten Aanvullende inhoudspakketten die een hoofd-app aanvullen Yes Windows 10 1709
Resourcepakketten Taal-, schaal- en toegankelijkheidsmiddelen gescheiden per markt Yes Windows 10

De juiste technologie kiezen

App-services gebruiken wanneer

  • U hebt tweerichtingscommunicatie tussen afzonderlijke apps nodig.
  • De consumenten-app verzendt een aanvraag en wacht op een antwoord.
  • U wilt een API-achtige interface beschikbaar maken voor andere apps.

Voorbeeld: Een vertaalservice die andere apps kunnen aanroepen om tekst te vertalen.

App-extensies gebruiken wanneer

  • Uw app heeft een invoegtoepassingsmodel nodig waarbij derden inhoud, thema's of invoegtoepassingen bieden.
  • Extensies worden tijdens runtime gedetecteerd vanuit geïnstalleerde pakketten.
  • Extensies bieden gegevens of configuratie, geen uitvoerbare code (code-uitvoering moet gebruikmaken van app-services).

Voorbeeld: Een afbeeldingseditor die filterpakketten vindt in geïnstalleerde uitbreidingspakketten.

Gebruik pakketextensies wanneer

  • U hebt een bredere uitbreidbaarheid op pakketniveau nodig voor Windows 11.
  • Extensies hebben toegang nodig tot meer pakketinhoud dan het PublicFolder model toestaat.

Optionele pakketten gebruiken wanneer

  • U hebt aanvullende inhoud (DLC, Premium-functies) die als afzonderlijke pakketten worden gedistribueerd.
  • Inhoud is geschreven door dezelfde uitgever.

Architectuurpatronen

App Service met extensiedetectie

Combineer app-extensies met app-services voor een volledige invoegtoepassingsarchitectuur:

  1. Uw host-app gebruikt AppExtensionCatalog om geïnstalleerde extensies te detecteren.
  2. Elke extensie declareert eigenschappen die de mogelijkheden beschrijven.
  3. Wanneer de gebruiker een extensie activeert, maakt de host-app verbinding met de app-service van de extensie voor communicatie in twee richtingen.
┌─────────────────┐      ┌──────────────────┐
│   Host app       │      │  Extension app    │
│                  │      │                   │
│ AppExtension     │◄────►│ AppExtension      │
│   Catalog        │      │   declaration     │
│                  │      │                   │
│ AppService       │◄────►│ AppService        │
│   Connection     │      │   provider        │
└─────────────────┘      └──────────────────┘

Alleen inhoudsextensie

Voor eenvoudigere scenario's waarbij extensies statische inhoud bieden (thema's, sjablonen, gegevensbestanden):

  1. De host-app detecteert extensies via AppExtensionCatalog.
  2. Het leest bestanden uit de extensie PublicFolder.
  3. Er is geen app-service nodig.

Verschillen met de uitbreidbaarheid van UWP

De hier beschreven uitbreidbaarheidstechnologieën werken op dezelfde manier in Windows App SDK desktop-apps als in UWP, met één vereiste: MSIX-pakketidentiteit. Alle uitbreidbaarheidsfuncties zijn afhankelijk van het pakketmanifest voor declaraties en de pakketcatalogus voor detectie.

Als uw desktop-app niet als pakket is verpakt, kunt u deze extensibility-technologieën niet gebruiken. Overweeg alternatieve benaderingen zoals:

  • COM-gebaseerde interfaces voor invoegtoepassingen
  • Detectie van extensie op basis van bestandssysteem
  • Benoemde pijpen of andere IPC-mechanismen

Bestandsgebaseerde detectie van plug-ins voor niet-verpakte apps

Voor uitgepakte WinUI 3-apps kunt u een invoegtoepassingssysteem implementeren met behulp van .NET AssemblyLoadContext om extensies uit een bekende map te laden:

public class PluginLoader
{
    private readonly string _pluginDirectory;

    public PluginLoader(string pluginDirectory)
    {
        _pluginDirectory = pluginDirectory;
    }

    public IEnumerable<T> LoadPlugins<T>() where T : class
    {
        if (!Directory.Exists(_pluginDirectory))
            yield break;

        foreach (var dll in Directory.GetFiles(_pluginDirectory, "*.dll"))
        {
            var context = new PluginLoadContext(dll);
            var assembly = context.LoadFromAssemblyPath(Path.GetFullPath(dll));

            foreach (var type in assembly.GetTypes()
                .Where(t => typeof(T).IsAssignableFrom(t) && !t.IsAbstract))
            {
                if (Activator.CreateInstance(type) is T plugin)
                    yield return plugin;
            }
        }
    }
}

// Custom AssemblyLoadContext to isolate plugin dependencies
public class PluginLoadContext : AssemblyLoadContext
{
    private readonly AssemblyDependencyResolver _resolver;

    public PluginLoadContext(string pluginPath) : base(isCollectible: true)
    {
        _resolver = new AssemblyDependencyResolver(pluginPath);
    }

    protected override Assembly? Load(AssemblyName assemblyName)
    {
        var path = _resolver.ResolveAssemblyToPath(assemblyName);
        return path != null ? LoadFromAssemblyPath(path) : null;
    }
}

Warning

Het laden van assembly's vanaf schijf zonder validatie is een beveiligingsrisico. Controleer in productie assemblyhandtekeningen (zoals Authenticode) voordat u ze laadt, beperk de ACL-rechten van de plug-inmap en overweeg plug-ins in een afzonderlijk proces met beperkte rechten uit te voeren.

Definieer een contract voor een gedeelde interface in een afzonderlijke assembly waarnaar zowel de host als de invoegtoepassingen verwijzen:

// Contoso.App.Contracts (shared assembly)
public interface IPluginExtension
{
    string Name { get; }
    string Description { get; }
    void Execute(IServiceProvider services);
}

Opmerking

Door isCollectible: true in de AssemblyLoadContext te gebruiken, kunt u invoegtoepassingen tijdens de runtime ontladen. Deze aanpak voorkomt de problemen met versiebeheer die MEF (Managed Extensibility Framework) in desktop-apps kunnen introduceren.