Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этой статье описаны шаги по созданию действий приложений и описаны компоненты приложения поставщика действий приложений. Действия приложений — это отдельные единицы поведения, которые приложение Windows может реализовать и зарегистрировать, чтобы они могли быть доступны из других приложений и возможностей, легко интегрируясь в рабочие процессы пользователей. Дополнительные сведения о действиях приложений в Windows см. в разделе "Действия приложений" в Обзоре Windows
Действия поддерживают две разные модели активации для поставщиков действий приложений: активацию COM и активацию запуска URI. В этой статье описываются шаги создания поставщика действий для приложения, который использует активацию COM.
Выполните одну из приведенных ниже команд в терминале (будь то разработчик C# или C++). При этом запускается файл конфигурации WinGet , выполняющий следующие задачи (уже установленные зависимости будут пропущены):
- Включает режим разработчика.
- Установка Visual Studio Community Edition
- Включите рабочие нагрузки для разработки приложений Windows и нагрузки C++ или .NET/C#
- Включите средства упаковки MSIX
Для разработчиков C#:
winget configure https://raw.githubusercontent.com/microsoft/winget-dsc/refs/heads/main/samples/Configuration%20files/Learn%20tutorials/Windows%20AI/app_actions_cs.winget
Для разработчиков C++:
winget configure https://raw.githubusercontent.com/microsoft/winget-dsc/refs/heads/main/samples/Configuration%20files/Learn%20tutorials/Windows%20AI/app_actions_cpp.winget
Создание проекта приложения Windows в Visual Studio
Функция "Действия приложений в Windows" поддерживается для нескольких платформ приложений, но приложения должны иметь удостоверение пакета для регистрации в системе. В этом пошаговом руководстве будет реализован поставщик действий для приложений Windows в упакованном настольном приложении C# WinUI 3.
В Visual Studio создайте проект.
В диалоговом окне "Создание проекта " задайте для фильтра языка значение "C#", а фильтр платформы — "WinUI", а затем выберите шаблон проекта "Пустое приложение, упакованое (WinUI 3 в desktop)".
Назовите новый проект ExampleAppActionProvider.
Когда проект загрузится, в Обозревателе решений щелкните правой кнопкой мыши по имени проекта и выберите Свойства. На странице общего
прокрутите страницу вниз до целевой ОС и выберите "Windows". Для целевой версии ОС и поддерживаемой версии ОС выберите версию 10.0.26100.0 или более поздней.Чтобы обновить проект для поддержки API поставщика действий, в обозревателе решений щелкните правой кнопкой мыши имя проекта и выберите "Изменить файл проекта". В PropertyGroup добавьте следующий элемент WindowsSdkPackageVersion .
<WindowsSdkPackageVersion>10.0.26100.59-preview</WindowsSdkPackageVersion>
Добавление JSON-файла определения действия
Приложения поставщика действий должны предоставить файл определения действия, определяющий действия, которые реализует приложение. Этот файл содержит сведения о входных и выходных данных действий и метаданных, таких как уникальный идентификатор и описание действий. Дополнительные сведения о формате JSON-файла действия приложения см. в схеме JSON определения действия для поставщиков действий приложений Windows.
В этом примере определяется одно действие с именем SendMessage, которое принимает одну сущность Text в качестве входных данных и возвращает одно значение TextEntity в качестве выходных данных. Помимо определения действий, JSON-файл также указывает, следует ли запускать приложение поставщика действий с помощью активации COM или запуска URI. В этом примере будет использоваться активация COM.
- В обозревателе решений щелкните правой кнопкой мыши файл проекта ExampleAppActionProvider и выберите add-New> Item....
- В диалоговом окне "Добавление нового элемента" выберите текстовый файл. Назовите новый файл "registration.json" и нажмите кнопку "ОК".
- Добавьте следующее определение действия JSON в файл registration.json.
- В обозревателе решений щелкните правой кнопкой мыши файл registration.json и выберите "Свойства". В области "Свойства" установите Действие сборки в значение "Content" и установите для параметра Копировать в выходной каталог значение "Копировать, если новее".
- Замените значение invocation.clsid новым GUID, который будет определять поставщика. Вы можете создать новый GUID в Visual Studio, перейдя в раздел "Сервис-создание> GUID". Этот GUID будет использоваться еще раз в нескольких разных местах в этом пошаговом руководстве.
{
"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"
}
}
]
}
Добавление класса ActionProvider для обработки операций действия
Поставщики действий должны реализовать интерфейс IActionProvider . Этот интерфейс требует реализации одного метода InvokeAsync, который система использует для вызова действия.
- В Visual Studio щелкните правой кнопкой мыши проект
AppActionProvider
в обозревателе решений и выберите Добавить ->Класс. - В диалоговом окне "Добавить класс " назовите класс ActionProvider и нажмите кнопку "Добавить".
- В созданном файле ActionProvider.cs обновите определение класса, чтобы указать, что он реализует интерфейс IActionProvider .
- Пометка класса с помощью System.Runtime.InteropServices.GuidAttribute. Это используется кодом активации COM, показанным далее в этом пошаговом руководстве. Обязательно обновите значение до значения, указанного в поле invocation.clsid в файле registration.json.
// AppActionProvider.cs
[System.Runtime.InteropServices.GuidAttribute("00001111-aaaa-2222-bbbb-3333cccc4444")]
public partial class AppActionProvider : IActionProvider
Реализуйте метод IActionProvider.InvokeAsync
Метод InvokeAsync имеет тип возвращаемого значения IAsyncAction. В этом примере используется вспомогательный класс, возвращающий задачу, который затем преобразуется в IAsyncAction с вызовом метода расширения AsAsyncAction . Добавьте следующее определение метода в класс AppActionProvider .
// AppActionProvider.cs
public IAsyncAction InvokeAsync(ActionInvocationContext context)
{
return InvokeAsyncHelper(context).AsAsyncAction();
}
В вспомогательном методе InvokeAsyncHelper выполняются следующие действия:
- ActionInvocationContext.GetInputEntities вызывается для получения набора сущностей, передаваемых в качестве входных данных в действие.
- Поставщик действий может поддерживать несколько действий, поэтому перед обработкой входных значений свойство ActionInvocationContext.ActionId вычисляется, чтобы определить, какое действие вызывается. Идентификатор будет значением, объявленным для действия в поле id в файле reisgration.json.
- В этом примере существует одна входная сущность типа TextActionEntity с именем message. Вспомогательный метод перебирает входные данные и проверяет ожидаемое имя.
- При обнаружении ожидаемого имени входной сущности он возвращается к типу TextEntity , а текст сообщения извлекается с помощью свойства Text . На этом этапе реальная реализация действия будет принимать это входное сообщение, выполнять некоторую обработку и генерировать ответ.
- В этом примере создается ответ TextEntity, как указано в поле выходных данных в файле registration.json. Сущность создается из жестко закодированных строк, а затем добавляется в качестве выходных данных путем вызова SetOutputEntity, передавая имя выходной сущности и объект TextEntity .
Добавьте следующее определение метода в класс 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;
}
}
Обновление файла манифеста пакета приложения
Файл Package.appmanifest содержит сведения о пакете MSIX для приложения. Чтобы зарегистрировать систему в качестве поставщика действий приложений Windows, приложение должно включать элемент uap3:Extension с параметром "Категория ", равным "windows.appExtension". Этот элемент используется для указания расположения JSON-файла Действия приложения, который определяет действия приложения. Дополнительные сведения о формате манифеста пакета приложения поставщика действий см. в формате XML манифеста пакета для приложения Windows App Action.
В данном учебном примере используется активация COM для запуска провайдера действий приложения. Чтобы включить активацию COM, используйте элемент com2:Extension в манифесте пакета приложения. Значение invocation.clsid , указанное в JSON-файле определения действия, должно соответствовать идентификатору класса, указанному в элементе com:Class в манифесте пакета приложения.
- Щелкните правой кнопкой мыши файл Package.appxmanifest и выберите команду View Code
- Добавьте следующие пространства имен в элемент 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"
- Добавьте следующий элемент Extensions в элемент Application и после элемента 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>
Реализовать фабрику классов, которая будет создавать экземпляр IActionProvider по запросу
После запуска приложения поставщика действий приложение должно вызвать CoRegisterClassObject , чтобы система может создать экземпляр COM-сервера для реализации IActionProvider . Для этой функции требуется реализация IClassFactory. В этом примере фабрика классов реализуется в автономном вспомогательном классе.
В Visual Studio щелкните правой кнопкой мыши проект ExampleAppActionProvider
в обозревателе решений и выберите Добавить ->Класс. В диалоговом окне Добавить класс наберите имя класса "FactoryHelper" и нажмите Добавить.
Замените содержимое файла FactoryHelper.cs следующим кодом. Этот код определяет интерфейс IClassFactory и реализует два метода CreateInstance и LockServer. Этот код является типичным шаблоном для реализации фабрики классов и не зависит от функциональности поставщика действий приложения, за исключением того, что созданный объект класса реализует интерфейс 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;
}
}
Реализуйте пользовательский метод "Main"
В шаблоне проекта по умолчанию точка входа основного метода автоматически создается компилятором. Этот пример отключит автоматическое создание Main , чтобы при запуске можно было запустить необходимый код активации.
- В обозревателе решений щелкните правой кнопкой мыши значок проекта и выберите "Изменить файл проекта".
- В элементе PropertyGroup добавьте следующий дочерний элемент, чтобы отключить автоматически созданную главную функцию.
<DefineConstants>$(DefineConstants);DISABLE_XAML_GENERATED_MAIN</DefineConstants>
Затем в обозревателе решений щелкните правой кнопкой мыши значок проекта и выберите "Добавить> класс". Измените имя файла на "Program.cs" и нажмите кнопку "Добавить".
В исполняемом файле Program.cs вызывается CoRegisterClassObject для регистрации COM-сервера поставщика действий. Замените содержимое Program.cs приведенным ниже кодом. Этот код импортирует функцию CoRegisterClassObject и вызывает ее, передавая класс ActionProviderFactory , определенный на предыдущем шаге. Обязательно обновите объявление переменной CLSID_Factory , чтобы использовать GUID, указанный в файле 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;
Проверка действия приложения Windows
Приложение "Тестовый игровой полигон для действий приложений" позволяет проверить регистрацию и функциональные возможности вашего приложения-поставщика действий для Windows. Для получения дополнительной информации об использовании этого инструмента см. App Actions Testing Playground.