Windows 上的应用操作入门

本文介绍了创建应用动作的步骤,并描述了应用动作提供者应用的组件。 应用作是 Windows 应用可以实现和注册的单个行为单元,以便可以从其他应用和体验访问它们,并无缝集成到用户工作流中。 有关 Windows 上的应用作的详细信息,请参阅 Windows 上的应用作概述

IActionProvider 接口是应用作提供程序用来与 Windows作框架通信的主要接口。 但是,Microsoft提供了 Microsoft.AI.Actions NuGet 包 ,该包基于代码中的 .NET 属性自动生成 IActionProvider 实现,使你能够生成强类型类来表示作。 这是实现应用作提供程序应用的建议方法,也是本文中所述的技术。 对于某些边缘方案,开发人员可能希望直接实现 IActionProvider 。 有关详细信息,请参阅 手动实现 IActionProvider

还可以使用 URI 启动激活(而不是 COM 激活)实现应用作提供程序,尽管不支持某些更高级的方案,例如来自作的流式处理文本响应。 有关详细信息,请参阅 在 Windows 上实现应用作的 URI 启动

  1. 在终端中运行以下命令(无论是 C# 还是C++开发人员)。 这会运行执行以下任务的 WinGet 配置文件 (将跳过已安装的依赖项):

    • 启用开发人员模式。
    • 安装 Visual Studio Community Edition
    • 包括 Windows 应用开发工作负载和C++或 .NET/C# 工作负载
    • 包括 MSIX 打包工具
winget configure https://raw.githubusercontent.com/microsoft/winget-dsc/refs/heads/main/samples/Configuration%20files/Learn%20tutorials/Windows%20AI/app_actions_cs.winget

在 Visual Studio 中创建新的 Windows 应用项目

多个应用框架支持 Windows 上的应用作功能,但应用必须具有包标识才能向系统注册。 本演练将在打包的 C# WinUI 3 桌面应用中实现 Windows 应用操作提供程序。

  1. 在 Visual Studio 中,创建新项目。

  2. 在“ 创建新项目 ”对话框中,将语言筛选器设置为“C#”,并将平台筛选器设置为“WinUI”,然后选择“空白应用,打包(桌面中的 WinUI 3)”项目模板。

  3. 将新项目命名为“ExampleAppActionProvider”。

  4. 加载项目时,在 解决方案资源管理器 中右键单击项目名称并选择“ 属性”。 在“常规 ”页上,向下滚动到“目标操作系统 ”,并选择“Windows”。 对于 目标 OS 版本 和支持 的 OS 版本,请选择版本 10.0.26100.0 或更高版本。

  5. 若要更新项目以支持作提供程序 API,请在 解决方案资源管理器 中右键单击项目名称并选择“ 编辑项目文件”。 在 PropertyGroup 内部,添加以下 WindowsSdkPackageVersion 元素。

    <WindowsSdkPackageVersion>10.0.26100.75</WindowsSdkPackageVersion>
    

添加对 Microsoft.AI.Actions Nuget 包的引用

本文中的示例使用 Microsoft.AI.Actions Nuget 包的代码生成功能。

  1. 解决方案资源管理器中,右键单击项目名称并选择“ 管理 NuGet 包...”
  2. 请确保位于 “浏览 ”选项卡上,并搜索 Microsoft.AI.Actions。
  3. 选择Microsoft.AI.Actions 并单击“安装”。

添加 ActionProvider 类来处理作作

以下部分演示如何实现自定义作提供程序类,该类使用 Microsoft.AI.Actions.Annotations 命名空间中的 .NET 属性来标识作的组件。 Microsoft.AI.Actions NuGet 包使用这些属性自动生成 IActionProvider 接口的基础实现。 这样,就可以为作创建强类型类,而无需直接与低级别作提供程序 API 交互。

  1. 在 Visual Studio 中,右键单击ExampleAppActionProvider解决方案资源管理器中的项目,然后选择“添加>类”。
  2. “添加类 ”对话框中,将类命名为“MyActionProvider”,然后单击“ 添加”。
  3. MyActionProvider.cs 的内容替换为以下代码。
using Microsoft.AI.Actions.Annotations;
using System.Threading.Tasks;
using Windows.AI.Actions;

namespace ExampleAppActionProvider
{
    [ActionProvider]
    public sealed class MyActionsProvider
    {
        [WindowsAction(
            Description = "Send a message to a contact",
            Icon = "ms-resource://Files/Assets/StoreLogo.png",
            FeedbackHandler = nameof(SendMessageFeedback),
            UsesGenerativeAI = false
        )]
        [WindowsActionInputCombination(
            Inputs = ["Contact"],
            Description = "Send message to '${Contact.Text}'"
        )]
        [WindowsActionInputCombination(
            Inputs = ["Contact", "Message"],
            Description = "Send '${Message.Text}' to '${Contact.Text}'"
        )]

        public async Task<SendMessageResult> SendMessage(
            [Entity(Name = "Contact")] string contact,
            [Entity(Name = "Message")] string? message,
            InvocationContext context)
        {
            // Your action logic here
            string result = await ProcessMessageAsync(contact, message);

            return new SendMessageResult
            {
                Text = context.EntityFactory.CreateTextEntity(result)
            };
        }
        
        public Task SendMessageFeedback(ActionFeedback feedback, InvocationContext context)
        {
            // Handle user feedback for the action
            return Task.CompletedTask;
        }

        public record SendMessageResult
        {
            public required TextActionEntity Text { get; init; }
        }

        public async Task<string> ProcessMessageAsync(string contact, string? message)
        {
            if (message != null)
            {
                return await Task.Run(() => $"Processed {contact}, {message}");
            }
            else
            {
                return await Task.Run(() => $"Processed {contact}");
            }
        }
    }
}

Microsoft.AI.Actions Nuget 包的代码生成功能在代码中使用 .NET 属性来确定应用提供的作的详细信息。 此示例使用以下属性:

Attribute Description
ActionProviderAttribute 此属性标识实现一个或多个作的类。
WindowsActionAttribute 此属性提供有关作的元数据,例如应用的用户可读说明和用户可向用户显示的图标文件。
WindowsActionInputCombinationAttribute 此属性声明一组输入实体,作可以接受为输入。 单个作可以支持多个输入组合。
EntityAttribute 指示类表示 ActionEntity

大多数受支持的属性直接映射到系统用于发现作的作定义 JSON 文件中的字段。 事实上,如本文稍后所示,Microsoft.AI.Actions 代码生成功能使用这些属性在生成时自动生成作定义 JSON 文件。 更新作提供程序类,添加或修改这些属性时,Nuget 包将重新生成作定义文件以反映所做的更改。 有关作定义 JSON 文件的详细信息,请参阅 Windows 上的应用作的作定义 JSON 架构

有关受支持属性的列表,请参阅 Microsoft.AI.Actions Nuget 包的自述文件。

更新应用包清单文件

Package.appmanifest 文件提供应用的 MSIX 包的详细信息。 若要由系统注册为 Windows 应用作提供程序,应用必须包含一个 uap3:Extension 元素,该元素的 Category 设置为“windows.appExtension”。 此元素用于指定定义应用作的 App Action JSON 文件的位置。 还必须指定com.microsoft.windows.ai.actionsuap3:AppExtension 元素的名称。 有关作提供程序应用包清单格式的详细信息,请参阅 Windows 应用作提供程序包清单 XML 格式

本演练中的示例使用 COM 激活来启动应用程序操作提供程序。 若要启用 COM 激活,请使用应用包清单中的 com2:Extension 元素。 作定义 JSON 文件中指定的 invocation.clsid 值必须与应用包清单中 com:Class 元素中指定的类 ID 匹配。

  1. 右键单击 Package.appxmanifest 文件,然后选择“查看代码
  2. 将以下命名空间添加到文件根目录的 Package 元素。
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. Application 元素和 VisualElements 元素之后添加以下 Extensions 元素。
<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>registration.json</Registration>
        </uap3:Properties>
    </uap3:AppExtension>
</uap3:Extension>
</Extensions>

实现自定义 Main 方法

在默认项目模板中, 方法入口点由编译器自动生成。 此示例将禁用 Main 的自动生成,以便可以在启动时运行必要的激活代码。

  1. 解决方案资源管理器中,右键单击项目图标,然后选择 “编辑项目文件”。
  2. PropertyGroup 元素中,添加以下子元素以禁用自动生成的主函数。
<DefineConstants>$(DefineConstants);DISABLE_XAML_GENERATED_MAIN</DefineConstants>

接下来,在 解决方案资源管理器中,右键单击项目图标,然后选择 “>添加新项”。 选择 代码文件。 将文件名更改为“Program.cs”,然后单击“ 添加”。

在Program.cs文件中,我们将添加一行代码,该代码行将导致作 nuget 包自动生成允许系统调用作提供程序的 COM 服务器激活。

ComServerRegisterActions.RegisterActions();

此示例 Main 方法中的 其余代码只是启动 WinUI 应用的样板代码。 将 Program.cs 的内容替换为以下代码。

namespace ExampleAppActionProvider;

public static class Program
{

    [global::System.STAThreadAttribute]
    static void Main(string[] args)
    {
        global::WinRT.ComWrappersSupport.InitializeComWrappers();
        ComServerRegisterActions.RegisterActions();
        global::Microsoft.UI.Xaml.Application.Start((p) =>
        {
            var context = new global::Microsoft.UI.Dispatching.DispatcherQueueSynchronizationContext(global::Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread());
            global::System.Threading.SynchronizationContext.SetSynchronizationContext(context);
            new App();
        });
    }
}

将 Microsoft.AI.Actions 配置属性添加到项目文件

Microsoft.AI.Actions Nuget 包的代码生成功能使用项目文件中定义的属性值在生成时配置其行为。 在 .csproj 文件中的第一个 PropertyGroup 元素中添加以下属性。

<GenerateActionRegistrationManifest>true</GenerateActionRegistrationManifest>
<ActionRegistrationManifest>Assets\registration.json</ActionRegistrationManifest>
<GenerateActionsWinRTComServer>true</GenerateActionsWinRTComServer>
<RootNamespace>ExampleAppActionProvider</RootNamespace>

下表对这些属性进行了说明:

资产 Description
GenerateActionRegistrationManifest 如果设置为 true ,作包将根据作提供程序类定义中的 .NET 属性自动生成作定义 JSON 文件。 请注意,每当生成项目时,都会覆盖对生成的作定义文件的手动更改。 因此,如果需要保留所做的手动更改,可以将此值设置为 false
ActionRegistrationManifest 自动生成的作定义 JSON 文件的包相对路径。 请注意,系统将在应用包清单文件中 uap3:AppExtension 元素的 PublicFolder 属性中指定的文件夹中查找。 因此,请确保此属性的路径和清单文件中声明的公用文件夹匹配。
GenerateActionsWinRTComServer 将此设置为 true ,以便从本文前面所示的 ComServerRegisterActions.RegisterActions 调用 Program.cs 中启用 COM Server 激活代码的自动生成。 如果此值设置为 false ,则需要实现自己的 COM 服务器激活。
RootNamespace 设置自动生成代码的根命名空间,以便可以从自己的代码访问它。

根据生成的 registration.json 文件进行更新

生成项目后,可以在解决方案资源管理器Assets 文件夹中查看生成的registration.json文件。

{
  "version": 2,
  "actions": [
    {
      "id": "ExampleAppActionProvider.MyActionsProvider.SendMessage",
      "description": "Send a message to a contact",
      "icon": "ms-resource://Files/Assets/StoreLogo.png",
      "usesGenerativeAI": false,
      "hasFeedbackHandler": true,
      "inputs": [
        {
          "name": "Contact",
          "kind": "Text"
        },
        {
          "name": "Message",
          "kind": "Text"
        }
      ],
      "inputCombinations": [
        {
          "inputs": [
            "Contact"
          ],
          "description": "Send message to '${Contact.Text}'"
        },
        {
          "inputs": [
            "Contact",
            "Message"
          ],
          "description": "Send '${Message.Text}' to '${Contact.Text}'"
        }
      ],
      "outputs": [
        {
          "name": "Text",
          "kind": "Text"
        }
      ],
      "invocation": {
        "type": "COM",
        "clsid": "11112222-bbbb-3333-cccc-4444dddd5555"
      }
    }
  ]
}

更新应用包清单文件中的 CLSID

首次生成作提供程序应用时,将收到警告: warning WASDK0012: The Action Provider type ExampleAppActionProvider.MyActionsProvider is not registering a ComServer with Class Id '00000000-0000-0000-0000-0000000' 这是因为自动生成 registration.json 的文件使用唯一 GUID 声明 COM 服务器的 clsid 。 生成项目后,打开 registration.json 该文件并注意该文件声明该作使用 COM 激活并指定 clsid 值。 替换应用包清单文件中 com:Class 元素中的 Id 属性的值以使用生成的 GUID。

例如,如果生成的registration.json文件中的 clsid 值是11112222-bbbb-3333-cccc-4444dddd5555,则更新后的 com:Class 元素如下所示:

<com:Class Id="11112222-bbbb-3333-cccc-4444dddd5555" DisplayName="ExampleAppActionProvider" />

允许的应用调用程序

已添加到作定义 JSON 架构的新字段 是允许的AppInvokers ,它指定应用程序用户模型 ID(AppUserModelIDs)的列表,该列表可以通过调用 GetActionsForInputsGetAllActions 来发现作。 支持通配符。 “*”将匹配所有 AppUserModelID。 建议对大多数作执行此作,除非有特定原因限制可以调用作的调用方。 如果省略 allowedAppInvokers 或为空列表,则任何应用都无法发现该作。 有关 AppUserModelID 的详细信息,请参阅 应用程序用户模型 ID

以下示例演示了 允许的AppInvokers 设置允许 所有应用发现关联作的建议做法。

"actions": [
    {
      "id": "ExampleAppActionProvider.MyActionsProvider.SendMessage",
      "description": "Send a message to a contact",
      "icon": "ms-resource://Files/Assets/StoreLogo.png",
      "usesGenerativeAI": false,
      "hasFeedbackHandler": true,
      "allowedAppInvokers" : ["*"],
    ...

重要

在当前的 Microsoft.AI.Actions 版本中,每当重新生成作定义文件时, 都会覆盖 allowedAppInvokers 。 将 allowedAppInvokers 添加到作定义 JSON 文件后,应在项目文件中将 GenerateActionRegistrationManifest 设置为 false 。 如果修改代码并需要再次启用 JSON 文件生成,请确保将 allowedAppInvokers 添加回文件,并再次禁用 JSON 文件生成。

测试 Windows 应用操作

应用操作测试游乐场应用允许你验证 Windows 应用操作提供程序应用的注册和功能。 有关使用此工具的更多信息,请参阅 App Actions 测试平台