Crear y hospedar una extensión de aplicación

En este artículo se muestra cómo crear una extensión de aplicación de Windows 10 y hospedarla en una aplicación. Las extensiones de aplicaciones se admiten en aplicaciones para UWP y aplicaciones de escritorio empaquetadas.

Para demostrar cómo crear una extensión de aplicación, en este artículo se usa el código XML del manifiesto de paquete y los fragmentos de código del ejemplo de código de extensión matemática. Este ejemplo es una aplicación para UWP, pero las características que se muestran en el ejemplo también se aplican a las aplicaciones de escritorio empaquetadas. Siga estas instrucciones para empezar a trabajar con el ejemplo:

  • Descargue y descomprima el ejemplo de código de extensión matemática.
  • En Visual Studio 2019, abra MathExtensionSample.sln. Establezca el tipo de compilación en x86 (Compilación>Configuration Manager y, a continuación, cambie Platform a x86 para ambos proyectos).
  • Implementar la solución: Compilar>implementación de la solución.

Introducción a las extensiones de aplicación

En Windows 10, las extensiones de aplicación proporcionan funcionalidad similar a lo que hacen los complementos, los complementos y los complementos en otras plataformas. Las extensiones de aplicación se introdujeron en Windows 10 Anniversary Edition (versión 1607, compilación 10.0.14393).

Las extensiones de aplicación son aplicaciones para UWP o aplicaciones de escritorio empaquetadas que tienen una declaración de extensión que les permite compartir contenido e eventos de implementación con una aplicación host. Una aplicación de extensión puede proporcionar varias extensiones.

Dado que las extensiones de aplicación son solo aplicaciones para UWP o aplicaciones de escritorio empaquetadas, también pueden ser aplicaciones totalmente funcionales, extensiones de host y proporcionar extensiones a otras aplicaciones, todo sin crear paquetes de aplicaciones independientes.

Al crear un host de extensión de aplicación, se crea una oportunidad para desarrollar un ecosistema en torno a la aplicación en el que otros desarrolladores pueden mejorar la aplicación de maneras en las que es posible que no haya esperado o tenido los recursos. Considere las extensiones de Microsoft Office, las extensiones de Visual Studio, las extensiones del explorador, etc. Estas crean experiencias más enriquecidas para esas aplicaciones que van más allá de la funcionalidad con la que se incluyen. Las extensiones pueden agregar valor y durabilidad a la aplicación.

En un nivel alto, para configurar una relación de extensión de aplicación, es necesario:

  1. Declare una aplicación para que sea un host de extensión.
  2. Declare una aplicación para que sea una extensión.
  3. Decida si implementar la extensión como un servicio de aplicaciones, una tarea en segundo plano o alguna otra manera.
  4. Defina cómo se comunicarán los hosts y sus extensiones.
  5. Use la API Windows.ApplicationModel.AppExtensions en la aplicación host para acceder a las extensiones.

Veamos cómo esto se hace examinando el ejemplo de código de extensión matemática que implementa una calculadora hipotética a la que puede agregar nuevas funciones mediante extensiones. En Microsoft Visual Studio 2019, cargue MathExtensionSample.sln desde el ejemplo de código.

Ejemplo de código de extensión matemática

Declarar una aplicación para que sea un host de extensión

Una aplicación se identifica como un host de extensión de aplicación declarando el <AppExtensionHost> elemento en su archivo Package.appxmanifest. Consulte el archivo Package.appxmanifest en el proyecto MathExtensionHost para ver cómo se hace esto.

Package.appxmanifest en el proyecto MathExtensionHost

<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>

Observe y la xmlns:uap3="http://..." presencia de uap3 en IgnorableNamespaces. Son necesarios porque usamos el espacio de nombres uap3.

<uap3:Extension Category="windows.appExtensionHost"> identifica esta aplicación como un host de extensión.

El elemento Name de <uap3:AppExtensionHost> es el nombre del contrato de extensión . Cuando una extensión especifica el mismo nombre de contrato de extensión, el host podrá encontrarlo. Por convención, se recomienda crear el nombre del contrato de extensión con el nombre de la aplicación o del publicador para evitar posibles colisiones con otros nombres de contrato de extensión.

Puede definir varios hosts y varias extensiones en la misma aplicación. En este ejemplo, declaramos un host. La extensión se define en otra aplicación.

Declaración de una aplicación para que sea una extensión

Una aplicación se identifica como una extensión de aplicación declarando el <uap3:AppExtension> elemento en su archivo Package.appxmanifest . Abra el archivo Package.appxmanifest en el proyecto MathExtension para ver cómo se hace esto.

Package.appxmanifest en el proyecto MathExtension:

<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>

De nuevo, observe la xmlns:uap3="http://..." línea y la presencia de uap3 en IgnorableNamespaces. Son necesarios porque usamos el uap3 espacio de nombres .

<uap3:Extension Category="windows.appExtension"> identifica esta aplicación como una extensión.

El significado de los <uap3:AppExtension> atributos es el siguiente:

Atributo Descripción Obligatorio
Nombre Este es el nombre del contrato de extensión. Cuando coincida con el nombre declarado en un host, ese host podrá encontrar esta extensión. ✔️
Id Identifica de forma única esta extensión. Dado que puede haber varias extensiones que usen el mismo nombre de contrato de extensión (imagine una aplicación de pintura que admite varias extensiones), puede usar el identificador para distinguirlos. Los hosts de extensión de aplicación pueden usar el identificador para deducir algo sobre el tipo de extensión. Por ejemplo, podría tener una extensión diseñada para escritorio y otra para dispositivos móviles, con el identificador siendo el diferenciador. También puede usar el elemento Properties , que se describe a continuación, para ello. ✔️
DisplayName Se puede usar desde la aplicación host para identificar la extensión al usuario. Es consultable desde y puede usar el nuevo sistema de administración de recursos (ms-resource:TokenName) para la localización. El contenido localizado se carga desde el paquete de extensión de la aplicación, no desde la aplicación host.
Descripción Se puede usar desde la aplicación host para describir la extensión al usuario. Es consultable desde y puede usar el nuevo sistema de administración de recursos (ms-resource:TokenName) para la localización. El contenido localizado se carga desde el paquete de extensión de la aplicación, no desde la aplicación host.
PublicFolder Nombre de una carpeta, relativa a la raíz del paquete, donde puede compartir contenido con el host de extensión. Por convención, el nombre es "Público", pero puede usar cualquier nombre que coincida con una carpeta de la extensión. ✔️

<uap3:Properties> es un elemento opcional que contiene metadatos personalizados que los hosts pueden leer en tiempo de ejecución. En el ejemplo de código, la extensión se implementa como un servicio de aplicaciones, por lo que el host necesita una manera de obtener el nombre de ese servicio de aplicaciones para que pueda llamarlo. El nombre del servicio de aplicaciones se define en el <elemento Service> , que definimos (podríamos haberlo llamado todo lo que queríamos). El host del ejemplo de código busca esta propiedad en tiempo de ejecución para obtener información sobre el nombre del servicio de aplicaciones.

Decida cómo implementará la extensión.

La sesión de compilación 2016 sobre extensiones de aplicación muestra cómo usar la carpeta pública que se comparte entre el host y las extensiones. En ese ejemplo, la extensión se implementa mediante un archivo JavaScript que se almacena en la carpeta pública, que invoca el host. Ese enfoque tiene la ventaja de ser ligero, no requiere compilación y puede admitir la realización de la página de aterrizaje predeterminada que proporciona instrucciones para la extensión y un vínculo a la página de Microsoft Store de la aplicación host. Consulte el ejemplo de código de extensión de aplicación build 2016 para obtener más información. En concreto, vea el proyecto InvertImageExtension y InvokeLoad() en ExtensionManager.cs en el proyecto ExtensibilitySample .

En este ejemplo, usaremos un servicio de aplicaciones para implementar la extensión. Los servicios de aplicaciones tienen las siguientes ventajas:

  • Si la extensión se bloquea, no quitará la aplicación host porque la aplicación host se ejecuta en su propio proceso.
  • Puede usar el idioma que prefiera para implementar el servicio. No tiene que coincidir con el idioma usado para implementar la aplicación host.
  • El servicio de aplicaciones tiene acceso a su propio contenedor de aplicaciones, que puede tener diferentes funcionalidades que el host.
  • Hay aislamiento entre los datos del servicio y la aplicación host.

Código de App Service de host

Este es el código de host que invoca el servicio de aplicaciones de la extensión:

ExtensionManager.cs en el proyecto MathExtensionHost

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
}

Este es el código típico para invocar un servicio de aplicaciones. Para más información sobre cómo implementar y llamar a un servicio de aplicaciones, consulte Creación y consumo de un servicio de aplicaciones.

Una cosa que hay que tener en cuenta es cómo se determina el nombre del servicio de aplicaciones que se va a llamar. Dado que el host no tiene información sobre la implementación de la extensión, la extensión debe proporcionar el nombre de su servicio de aplicaciones. En el ejemplo de código, la extensión declara el nombre del servicio de aplicaciones en su archivo en el <uap3:Properties> elemento :

Package.appxmanifest en el proyecto MathExtension

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

Puede definir su propio XML en el <uap3:Properties> elemento . En este caso, definimos el nombre del servicio de aplicaciones para que el host pueda hacerlo cuando invoque la extensión.

Cuando el host carga una extensión, el código como este extrae el nombre del servicio de las propiedades definidas en package.appxmanifest de la extensión:

Update() en ExtensionManager.cs, en el proyecto MathExtensionHost

...
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

Con el nombre del servicio de aplicaciones almacenado en _serviceName, el host puede usarlo para invocar el servicio de aplicaciones.

Llamar a un servicio de aplicaciones también requiere el nombre de familia del paquete que contiene el servicio de aplicaciones. Afortunadamente, la API de extensión de aplicación proporciona esta información que se obtiene en la línea: connection.PackageFamilyName = AppExtension.Package.Id.FamilyName;

Definir cómo se comunicará el host y la extensión

Los servicios de aplicaciones usan un elemento ValueSet para intercambiar información. Como autor del host, debe tener un protocolo para comunicarse con extensiones que es flexible. En el ejemplo de código, esto significa tener en cuenta las extensiones que pueden tomar 1, 2 o más argumentos en el futuro.

En este ejemplo, el protocolo para los argumentos es un ValueSet que contiene los pares clave-valor denominado "Arg" + el número de argumento, por ejemplo, Arg1 y Arg2. El host pasa todos los argumentos de ValueSet y la extensión usa las que necesita. Si la extensión puede calcular un resultado, el host espera que valueSet devuelto de la extensión tenga una clave denominada Result que contenga el valor del cálculo. Si esa clave no está presente, el host asume que la extensión no pudo completar el cálculo.

Código de App Service de extensión

En el ejemplo de código, el servicio de aplicaciones de la extensión no se implementa como una tarea en segundo plano. En su lugar, usa el modelo de App Service de procedimiento único en el que el servicio de aplicaciones se ejecuta en el mismo proceso que la aplicación de extensión que la hospeda. Esto sigue siendo un proceso diferente de la aplicación host, lo que proporciona las ventajas de la separación de procesos, al tiempo que obtiene algunas ventajas de rendimiento al evitar la comunicación entre procesos cruzados entre el proceso de extensión y el proceso en segundo plano que implementa el servicio de aplicaciones. Consulte Conversión de un servicio de aplicaciones para que se ejecute en el mismo proceso que su aplicación host para ver la diferencia entre un servicio de aplicaciones que se ejecuta como una tarea en segundo plano frente a en el mismo proceso.

El sistema se convierte en OnBackgroundActivate() cuando se activa el servicio de aplicaciones. Ese código configura controladores de eventos para controlar la llamada real de App Service cuando se trata de (OnAppServiceRequestReceived()), así como para tratar eventos de limpieza, como obtener un objeto de aplazamiento que controla un evento de cancelación o cerrado.

App.xaml.cs en el proyecto MathExtension.

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;
    }
}

El código que realiza el trabajo de la extensión está en OnAppServiceRequestReceived(). Se llama a esta función cuando se invoca el servicio de aplicaciones para realizar un cálculo. Extrae los valores que necesita de ValueSet. Si puede realizar el cálculo, coloca el resultado, bajo una clave denominada Result, en el ValueSet que se devuelve al host. Recuerde que, según el protocolo definido para la forma en que este host y sus extensiones se comunicarán, la presencia de una clave de resultado indicará que se ha realizado correctamente; de lo contrario, se produce un error.

App.xaml.cs en el proyecto MathExtension.

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();
}

Administración de extensiones

Ahora que hemos visto cómo implementar la relación entre un host y sus extensiones, veamos cómo un host encuentra las extensiones instaladas en el sistema y reacciona a la adición y eliminación de paquetes que contienen extensiones.

Microsoft Store ofrece extensiones como paquetes. AppExtensionCatalog busca paquetes instalados que contienen extensiones que coinciden con el nombre del contrato de extensión del host y proporciona eventos que se activan cuando se instala o quita un paquete de extensión de aplicación relevante para el host.

En el ejemplo de código, la ExtensionManager clase (definida en ExtensionManager.cs en el proyecto MathExtensionHost ) ajusta la lógica para cargar extensiones y responder a las instalaciones y desinstalaciones del paquete de extensión.

El ExtensionManager constructor usa AppExtensionCatalog para buscar las extensiones de aplicación en el sistema que tienen el mismo nombre de contrato de extensión que el host:

ExtensionManager.cs en el proyecto MathExtensionHost.

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

Cuando se instala un paquete de extensión, ExtensionManager recopila información sobre las extensiones del paquete que tienen el mismo nombre de contrato de extensión que el host. Una instalación puede representar una actualización en cuyo caso se actualiza la información de la extensión afectada. Cuando se desinstala un paquete de extensión, ExtensionManager quita información sobre las extensiones afectadas para que el usuario sepa qué extensiones ya no están disponibles.

La Extension clase (definida en ExtensionManager.cs en el proyecto MathExtensionHost ) se creó para que el ejemplo de código acceda al identificador, la descripción, el logotipo y la información específica de la aplicación de una extensión, como si el usuario ha habilitado la extensión.

Para decir que la extensión se carga (vea Load()en ExtensionManager.cs) significa que el estado del paquete es correcto y que hemos obtenido su identificador, logotipo, descripción y carpeta pública (que no usamos en este ejemplo, solo para mostrar cómo se obtiene). El propio paquete de extensión no se está cargando.

El concepto de descarga se usa para realizar un seguimiento de las extensiones que ya no se deben presentar al usuario.

ExtensionManager proporciona instancias de colección Extension para que las extensiones, sus nombres, descripciones y logotipos puedan enlazarse a la interfaz de usuario. La página ExtensionsTab se enlaza a esta colección y proporciona la interfaz de usuario para habilitar o deshabilitar extensiones, así como para quitarlas.

Interfaz de usuario de ejemplo de pestaña Extensiones

Cuando se quita una extensión, el sistema solicita al usuario que compruebe que desea desinstalar el paquete que contiene la extensión (y posiblemente contiene otras extensiones). Si el usuario acepta, el paquete se desinstala y ExtensionManager quita las extensiones del paquete desinstalado de la lista de extensiones disponibles para la aplicación host.

Desinstalación de la interfaz de usuario

Depuración de extensiones y hosts de aplicaciones

A menudo, el host de extensión y la extensión no forman parte de la misma solución. En ese caso, para depurar el host y la extensión:

  1. Cargue el proyecto host en una instancia de Visual Studio.
  2. Cargue la extensión en otra instancia de Visual Studio.
  3. Inicie la aplicación host en el depurador.
  4. Inicie la aplicación de extensión en el depurador. (Si quiere implementar la extensión, en lugar de depurarla, para probar el evento de instalación del paquete del host, realice la > implementación de la solución en su lugar).

Ahora podrá alcanzar puntos de interrupción en el host y la extensión. Si inicia la depuración de la propia aplicación de extensión, verá una ventana en blanco para la aplicación. Si no desea ver la ventana en blanco, puede cambiar la configuración de depuración del proyecto de extensión para que no inicie la aplicación, sino depurarla cuando se inicie (haga clic con el botón derecho en el proyecto de extensión, Propiedades>depurar> seleccione No iniciar, pero depurar mi código cuando se inicie). Todavía tendrá que iniciar la depuración (F5) el proyecto de extensión, pero esperará hasta que el host active la extensión y, a continuación, se alcanzarán los puntos de interrupción de la extensión.

Depuración del ejemplo de código

En el ejemplo de código, el host y la extensión se encuentran en la misma solución. Haga lo siguiente para depurar:

  1. Asegúrese de que MathExtensionHost es el proyecto de inicio (haga clic con el botón derecho en el proyecto MathExtensionHost , haga clic en Establecer como proyecto de inicio).
  2. Coloque un punto Invoke de interrupción en ExtensionManager.cs, en el proyecto MathExtensionHost .
  3. F5 para ejecutar el proyecto MathExtensionHost .
  4. Coloque un punto OnAppServiceRequestReceived de interrupción en en App.xaml.cs en el proyecto MathExtension .
  5. Inicie la depuración del proyecto MathExtension (haga clic con el botón derecho en el proyecto MathExtension , Depurar iniciar > nueva instancia), que lo implementará y desencadenará el evento de instalación del paquete en el host.
  6. En la aplicación MathExtensionHost , vaya a la página Cálculo y haga clic en x^y para activar la extensión. El Invoke() punto de interrupción se alcanza primero y puede ver que se realiza la llamada de App Service de extensiones. A continuación, se alcanza el OnAppServiceRequestReceived() método de la extensión y puede ver que app service calcula el resultado y lo devuelve.

Solución de problemas de extensiones implementadas como un servicio de aplicaciones

Si el host de extensión tiene problemas para conectarse al servicio de aplicaciones de la extensión, asegúrese de que el <uap:AppService Name="..."> atributo coincida con lo que ha colocado en el <Service> elemento. Si no coinciden, el nombre del servicio que proporciona la extensión no coincidirá con el nombre del servicio de aplicaciones que implementó y el host no podrá activar la extensión.

Package.appxmanifest en el proyecto MathExtension:

<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>   

Lista de comprobación de escenarios básicos para probar

Al compilar un host de extensión y está listo para probar el nivel de compatibilidad de las extensiones, estos son algunos escenarios básicos para probar:

  • Ejecute el host y, a continuación, implemente una aplicación de extensión.
    • ¿El host recoge nuevas extensiones que vienen mientras se ejecuta?
  • Implemente la aplicación de extensión y, a continuación, implemente y ejecute el host.
    • ¿El host recoge las extensiones existentes anteriormente?
  • Ejecute el host y, a continuación, quite la aplicación de extensión.
    • ¿El host detecta la eliminación correctamente?
  • Ejecute el host y actualice la aplicación de extensión a una versión más reciente.
    • ¿El host recoge el cambio y descarga correctamente las versiones anteriores de la extensión?

Escenarios avanzados para probar:

  • Ejecute el host, mueva la aplicación de extensión a medios extraíbles, quite los medios.
    • ¿El host detecta el cambio en el estado del paquete y deshabilita la extensión?
  • Ejecute el host y, a continuación, dañe la aplicación de extensión (por lo que no es válida, firmada de forma diferente, etc.).
    • ¿Detecta el host la extensión manipulada y la controla correctamente?
  • Ejecute el host y, a continuación, implemente una aplicación de extensión que tenga contenido o propiedades no válidos.
    • ¿El host detecta contenido no válido y lo controla correctamente?

Consideraciones de diseño

  • Proporcione la interfaz de usuario que muestra al usuario qué extensiones están disponibles y les permite habilitarlas o deshabilitarlas. También puede considerar la posibilidad de agregar glifos para extensiones que dejen de estar disponibles porque un paquete se queda sin conexión, etc.
  • Dirija al usuario a dónde puede obtener extensiones. Quizás la página de extensión puede proporcionar una consulta de búsqueda de Microsoft Store que muestre una lista de extensiones que se pueden usar con la aplicación.
  • Considere cómo notificar al usuario la adición y eliminación de extensiones. Puede crear una notificación para cuando se instala una nueva extensión e invitar al usuario a habilitarla. Las extensiones deben deshabilitarse de forma predeterminada para que los usuarios estén en control.

Cómo difieren las extensiones de aplicación de los paquetes opcionales

El diferenciador clave entre los paquetes opcionales y las extensiones de aplicación son el ecosistema abierto frente al ecosistema cerrado y el paquete dependiente frente al paquete independiente.

Las extensiones de aplicación participan en un ecosistema abierto. Si la aplicación puede hospedar extensiones de aplicación, cualquier persona puede escribir una extensión para el host siempre que cumplan con el método de pasar o recibir información de la extensión. Esto difiere de los paquetes opcionales que participan en un ecosistema cerrado en el que el publicador decide quién puede hacer un paquete opcional que se puede usar con la aplicación.

Las extensiones de aplicación son paquetes independientes y pueden ser aplicaciones independientes. No pueden tener una dependencia de implementación en otra aplicación. Los paquetes opcionales requieren el paquete principal y no se pueden ejecutar sin él.

Un paquete de expansión para un juego sería un buen candidato para un paquete opcional porque está estrechamente enlazado al juego, no se puede ejecutar independientemente del juego, y es posible que no quieras que los paquetes de expansión los cree cualquier desarrollador del ecosistema.

Si ese mismo juego tuviera complementos de interfaz de usuario personalizables o temas, una extensión de aplicación podría ser una buena opción porque la aplicación que proporciona la extensión podría ejecutarse por sí misma y cualquier tercero podría hacerlos.

Comentarios

En este tema se proporciona una introducción a las extensiones de aplicación. Los aspectos clave que hay que tener en cuenta son la creación del host y marcarlo como tal en su archivo Package.appxmanifest, creando la extensión y marcando como tal en su archivo Package.appxmanifest, determinando cómo implementar la extensión (como un servicio de aplicaciones, una tarea en segundo plano u otros medios), definiendo cómo se comunicará el host con extensiones, y el uso de la API AppExtensions para acceder a las extensiones y administrarlas.