Dela via


Kom igång med App Actions i Windows

Den här artikeln beskriver stegen för att skapa appåtgärder och beskriver komponenterna i en appåtgärdsproviderapp. Appåtgärder är enskilda beteendeenheter som en Windows-app kan implementera och registrera så att de kan nås från andra appar och upplevelser och smidigt integreras i användararbetsflöden. Mer information om appåtgärder i Windows finns i Appåtgärder i Windows Översikt

Åtgärder stöder två olika aktiveringsmodeller för appåtgärdsleverantörer, COM-aktivering och URI-lanseringsaktivering. Den här artikeln går igenom stegen för att skapa en appåtgärdsprovider som använder COM-aktivering.

  1. Kör något av kommandona nedan i Terminal (oavsett om du är C# eller C++-utvecklare). Detta kör en WinGet-konfigurationsfil som utför följande uppgifter (redan installerade beroenden hoppas över):

    • Aktiverar utvecklarläge.
    • Installerar Visual Studio Community Edition
    • Inkludera arbetsbelastningar för Windows App-utveckling och antingen C++ eller .NET/C#-arbetsbelastningar
    • Inkludera MSIX-paketeringsverktyg

För C#-utvecklare:

winget configure https://raw.githubusercontent.com/microsoft/winget-dsc/refs/heads/main/samples/Configuration%20files/Learn%20tutorials/Windows%20AI/app_actions_cs.winget

För C++-utvecklare:

winget configure https://raw.githubusercontent.com/microsoft/winget-dsc/refs/heads/main/samples/Configuration%20files/Learn%20tutorials/Windows%20AI/app_actions_cpp.winget

Skapa ett nytt Windows-appprojekt i Visual Studio

Funktionen Appåtgärder i Windows stöds för flera appramverk, men appar måste ha paketidentitet för att kunna registrera sig i systemet. Den här genomgången implementerar en Windows App Action-provider i en paketerad C# WinUI 3-skrivbordsapp.

  1. Skapa ett nytt projekt i Visual Studio.

  2. I dialogrutan Skapa ett nytt projekt anger du språkfiltret till "C#" och plattformsfiltret till "WinUI" och väljer sedan projektmallen "Tom app, paketerad (WinUI 3 i desktop)".

  3. Ge det nya projektet namnet "ExampleAppActionProvider".

  4. När projektet läses in, i Solution Explorer högerklicka på projektnamnet och välj Egenskaper. På sidan Allmänt rullar du ned till Måloperativsystem och väljer "Windows". Välj version 10.0.26100.0 eller senare för Måloperativsystemversion och Operativsystemversion som stöds.

  5. Om du vill uppdatera projektet för att stödja API:erna för åtgärdsprovidern högerklickar du på projektnamnet i Solution Explorer och väljer Redigera projektfil. I PropertyGroup lägger du till följande WindowsSdkPackageVersion-element .

    <WindowsSdkPackageVersion>10.0.26100.59-preview</WindowsSdkPackageVersion>
    

Lägga till en JSON-fil för åtgärdsdefinition

Åtgärdsproviderappar måste tillhandahålla en åtgärdsdefinitionsfil som definierar de åtgärder som appen implementerar. Den här filen innehåller information om indata och utdata för dina åtgärder och metadata, till exempel en unik identifierare och en beskrivning av dina åtgärder. Mer information om JSON-filformatet för appåtgärd finns i JSON-schema för åtgärdsdefinition för Windows App Action-leverantörer.

I det här exemplet definieras en åtgärd med namnet SendMessage, som tar en enskild textentitet som indata och returnerar en enda TextEntity som utdata. Förutom att definiera åtgärder anger JSON-filen även om åtgärdsproviderappen ska startas med COM-aktivering eller via URI-start. I det här exemplet används COM-aktivering.

  1. Högerklicka på projektfilen ExampleAppActionProvider i Solution Explorer och välj Lägg till> nytt objekt....
  2. I dialogrutan Lägg till nytt objekt väljer du Textfil. Ge den nya filen namnet "registration.json" och klicka på OK.
  3. Lägg till följande JSON-åtgärdsdefinition i registration.json-filen.
  4. Högerklicka på filen registration.json i Solution Explorer och välj Egenskaper. I fönstret Egenskaper anger du Skapa åtgärd till "Innehåll" och anger Kopiera till Utdatakatalog till "Kopiera om nyare".
  5. Ersätt värdet invocation.clsid med ett nytt GUID som identifierar providern. Du kan generera ett nytt GUID i Visual Studio genom att gå till Verktyg-Skapa> GUID. Detta GUID används igen på några olika platser i den här genomgången.
{
  "version": 2,
  "actions": [
    {
      "id": "ExampleAppActionProvider.SendMessage",
      "description": "Send a message",
      "icon": "ms-resource://Files/Assets/StoreLogo.png",
      "usesGenerativeAI": false,
      "inputs": [
        {
          "name": "message",
          "kind": "Text"
        }
      ],
      "inputCombinations": [
        {
          "inputs": [
            "message"
          ],
          "description": "Send message '${message.Text}'"
        }
      ],
      "outputs": [
        {
          "name": "response",
          "kind": "Text"
        }
      ],
      "invocation": {
        "type": "COM",
        "clsid": "00001111-aaaa-2222-bbbb-3333cccc4444"
      }
    }
  ]
}

Lägga till en ActionProvider-klass för att hantera åtgärdsåtgärder

Åtgärdsprovidrar måste implementera gränssnittet IActionProvider . Det här gränssnittet kräver implementering av en enda metod, InvokeAsync, som systemet använder för att anropa en åtgärd.

  1. I Visual Studio högerklickar du på projektet AppActionProvider i Solution Explorer och väljer Lägg till>klass.
  2. I dialogrutan Lägg till klass ger du klassen namnet "ActionProvider" och klickar på Lägg till.
  3. I den genererade ActionProvider.cs-filen uppdaterar du klassdefinitionen så att den anger att den implementerar gränssnittet IActionProvider .
  4. Märk klassen med System.Runtime.InteropServices.GuidAttribute. Detta används av COM-aktiveringskoden som visas senare i den här genomgången. Se till att uppdatera värdet till det värde som anges i fältet invocation.clsid i filen registration.json.
// AppActionProvider.cs
[System.Runtime.InteropServices.GuidAttribute("00001111-aaaa-2222-bbbb-3333cccc4444")] 
public partial class AppActionProvider : IActionProvider

Implementera IActionProvider.InvokeAsync

Metoden InvokeAsync har en returtyp av IAsyncAction. I det här exemplet används en hjälpklass som returnerar en aktivitet, som sedan konverteras till en IAsyncAction med ett anrop till AsAsyncAction-tilläggsmetoden . Lägg till följande metoddefinition i klassen AppActionProvider .

// AppActionProvider.cs
public IAsyncAction InvokeAsync(ActionInvocationContext context)
{
    return InvokeAsyncHelper(context).AsAsyncAction();
}

I hjälpmetoden InvokeAsyncHelper utförs följande åtgärder:

  • ActionInvocationContext.GetInputEntities anropas för att hämta den uppsättning entiteter som skickas som indata till åtgärden.
  • En åtgärdsprovider kan ha stöd för flera åtgärder, så innan indatavärdena bearbetas utvärderas egenskapen ActionInvocationContext.ActionId för att avgöra vilken åtgärd som anropas. ID:t är det värde som deklareras för åtgärden i ID-fältet i filen reisgration.json.
  • I det här exemplet finns det en enda indataentitet av typen TextActionEntity med namnet "message". Hjälpmetoden loopar genom indata och söker efter det förväntade namnet.
  • När det förväntade indataentitetsnamnet hittas skickas det till typen TextEntity och meddelandetexten hämtas med egenskapen Text . I det här läget skulle en verklig implementering av en åtgärd ta det här indatameddelandet, bearbeta det och generera ett svar.
  • Det här exemplet skapar ett svar TextEntity, enligt beskrivningen i fältet utdata i filen registration.json. Entiteten skapas från en hårdkodad sträng och läggs sedan till som utdata genom att anropa SetOutputEntity och skicka in utdataentitetsnamnet och TextEntity-objektet .

Lägg till följande metoddefinition i klassen AppActionProvider .

// AppActionProvider.cs
async Task InvokeAsyncHelper(ActionInvocationContext context)
{
    NamedActionEntity[] inputs = context.GetInputEntities();

    var actionId = context.ActionId;
    switch (actionId)
    {
      case "ExampleActionProvider.SendMessage":
          foreach (NamedActionEntity inputEntity in inputs)
          {
              if (inputEntity.Name.Equals("message", StringComparison.Ordinal))
              {
                
                TextActionEntity entity = (TextActionEntity)(inputEntity.Entity);
                string message = entity.Text;
                
                // TODO: Process the message and generate a response

                string response = "This is the message response"; 
                TextActionEntity result = context.EntityFactory.CreateTextEntity(response);
                context.SetOutputEntity("response", result);

              }

          }

          break;

      default:

          break;

  }

}

Uppdatera apppaketets manifestfil

Filen Package.appmanifest innehåller information om MSIX-paketet för en app. För att kunna registreras av systemet som en Windows App Action-provider måste appen innehålla ett uap3:Extension-element med kategorin inställd på "windows.appExtension". Det här elementet används för att ange platsen för JSON-filen appåtgärd som definierar appens åtgärder. Mer information om manifestformatet för åtgärdsproviderns apppaket finns i XML-format för Paketmanifest för Windows App Action Provider.

I exemplet i den här genomgången används COM-aktivering för att starta appåtgärdsprovidern. Om du vill aktivera COM-aktivering använder du com2:Extension-elementet i apppaketmanifestet. Värdet invocation.clsid som anges i JSON-filen för åtgärdsdefinition måste matcha klass-ID:t som anges i com:Class-elementet i apppaketmanifestet.

  1. Högerklicka på filen Package.appxmanifest och välj Visa kod
  2. Lägg till följande namnområden i paketelementet i filens rot.
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
xmlns:com2="http://schemas.microsoft.com/appx/manifest/com/windows10/2"
xmlns:com3="http://schemas.microsoft.com/appx/manifest/com/windows10/3"
  1. Lägg till följande tilläggselement i programelementet och efter elementet VisualElements .
<Extensions>
  <com2:Extension Category="windows.comServer">
    <com2:ComServer>
        <com3:ExeServer Executable="ExampleAppActionProvider.exe" DisplayName="ExampleAppActionProvider">
            <com:Class Id="00001111-aaaa-2222-bbbb-3333cccc4444" DisplayName="ExampleAppActionProvider" />
        </com3:ExeServer>
      </com2:ComServer>
    </com2:Extension>
    <uap3:Extension Category="windows.appExtension">
        <uap3:AppExtension Name="com.microsoft.windows.ai.actions" DisplayName="Example App Action Provider" Id="appactionprovider" PublicFolder="Assets">
        <uap3:Properties>
            <Registration xmlns="">registration.json</Registration>
        </uap3:Properties>
    </uap3:AppExtension>
</uap3:Extension>
</Extensions>

Implementera en klassfabrik som instansierar IActionProvider på begäran

När systemet startar åtgärdsproviderappen måste appen anropa CoRegisterClassObject så att systemet kan instansiera COM-servern för IActionProvider-implementeringen . Den här funktionen kräver en implementering av IClassFactory. Det här exemplet implementerar klassfabriken i en fristående hjälpklass.

I Visual Studio högerklickar du på projektet ExampleAppActionProvider i Solution Explorer och väljer Lägg till>klass. I dialogrutan Lägg till klass ger du klassen namnet "FactoryHelper" och klickar på Lägg till.

Ersätt innehållet i FactoryHelper.cs-filen med följande kod. Den här koden definierar gränssnittet IClassFactory och implementerar dess två metoder, CreateInstance och LockServer. Den här koden är typisk för implementering av en klassfabrik och är inte specifik för funktionerna i en appåtgärdsprovider, förutom att den anger att klassobjektet som skapas implementerar gränssnittet IActionProvider .

// FactoryHelper.cs

using Microsoft.Windows.Widgets.Providers;
using System.Runtime.InteropServices;
using WinRT;

namespace COM
{
    static class Guids
    {
        public const string IClassFactory = "00000001-0000-0000-C000-000000000046";
        public const string IUnknown = "00000000-0000-0000-C000-000000000046";
    }

    /// 
    /// IClassFactory declaration
    /// 
    [ComImport, ComVisible(false), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(COM.Guids.IClassFactory)]
    internal interface IClassFactory
    {
        [PreserveSig]
        int CreateInstance(IntPtr pUnkOuter, ref Guid riid, out IntPtr ppvObject);
        [PreserveSig]
        int LockServer(bool fLock);
    }

    [ComVisible(true)]
    class WidgetProviderFactory<T> : IClassFactory
    where T : IActionProvider, new()
    {
        public int CreateInstance(IntPtr pUnkOuter, ref Guid riid, out IntPtr ppvObject)
        {
            ppvObject = IntPtr.Zero;

            if (pUnkOuter != IntPtr.Zero)
            {
                Marshal.ThrowExceptionForHR(CLASS_E_NOAGGREGATION);
            }

            if (riid == typeof(T).GUID || riid == Guid.Parse(COM.Guids.IUnknown))
            {
                // Create the instance of the .NET object
                ppvObject = MarshalInspectable<IActionProvider>.FromManaged(new T());
            }
            else
            {
                // The object that ppvObject points to does not support the
                // interface identified by riid.
                Marshal.ThrowExceptionForHR(E_NOINTERFACE);
            }

            return 0;
        }

        int IClassFactory.LockServer(bool fLock)
        {
            return 0;
        }

        private const int CLASS_E_NOAGGREGATION = -2147221232;
        private const int E_NOINTERFACE = -2147467262;

    }
}

Implementera en anpassad Main-metod

I standardprojektmallen genereras startpunkten för Main-metoden automatiskt av kompilatorn. Det här exemplet inaktiverar autogenereringen av Main så att den nödvändiga aktiveringskoden kan köras vid start.

  1. Högerklicka på projektikonen i Solution Explorer och välj Redigera projektfil.
  2. I elementet PropertyGroup lägger du till följande underordnade element för att inaktivera den automatiskt genererade huvudfunktionen.
<DefineConstants>$(DefineConstants);DISABLE_XAML_GENERATED_MAIN</DefineConstants>

Högerklicka sedan på projektikonen i Solution Explorer och välj Lägg till> klass. Ändra filnamnet till "Program.cs" och klicka på Lägg till.

I den Program.cs filen för den körbara filen anropas CoRegisterClassObject för att registrera åtgärdsproviderns COM-server. Ersätt innehållet i Program.cs med följande kod. Den här koden importerar funktionen CoRegisterClassObject och anropar den och skickar klassen ActionProviderFactory som definierades i ett tidigare steg. Se till att uppdatera CLSID_Factory variabeldeklarationen så att den använder det GUID som du angav i filen registration.json.

// Program.cs

using System.Runtime.InteropServices;
using ComTypes = System.Runtime.InteropServices.ComTypes;
using Microsoft.Windows.Widgets;
using ExampleWidgetProvider;
using COM;
using System;


[DllImport("ole32.dll")]

static extern int CoRegisterClassObject(
            [MarshalAs(UnmanagedType.LPStruct)] Guid rclsid,
            [MarshalAs(UnmanagedType.IUnknown)] object pUnk,
            uint dwClsContext,
            uint flags,
            out uint lpdwRegister);

[DllImport("ole32.dll")] static extern int CoRevokeClassObject(uint dwRegister);

uint cookie;

Guid CLSID_Factory = Guid.Parse("00001111-aaaa-2222-bbbb-3333cccc4444");
CoRegisterClassObject(CLSID_Factory, new ActionProviderFactory<AppActionProvider>(), 0x4, 0x1, out cookie);

Application.Start((p) =>
{
    var context = new DispatcherQueueSynchronizationContext(
        DispatcherQueue.GetForCurrentThread());
    SynchronizationContext.SetSynchronizationContext(context);
    _ = new App();
});

PInvoke.CoRevokeClassObject(cookie);

return 0;

Testa Windows-appåtgärden

Med appen App Actions Testing Playground kan du verifiera registreringen och funktionerna i din Windows App Action-providerapp. Mer information om hur du använder det här verktyget finns i Testlekplats för appåtgärder.