Создание событий в компонентах среды выполнения Windows
Примечание.
Дополнительные сведения о создании событий в компоненте C++/WinRT среда выполнения Windows см. в статье "Создание событий в C++/WinRT".
Если компонент среда выполнения Windows вызывает событие определяемого пользователем типа делегата в фоновом потоке (рабочем потоке), и JavaScript сможет получать событие, то его можно реализовать и/или вызвать в любом из этих способов.
- (Вариант 1) Вызовите событие через Windows.UI.Core.CoreDispatcher , чтобы маршалировать событие в контекст потока JavaScript. Хотя обычно это лучший вариант, в некоторых сценариях он может не обеспечить самую быструю производительность.
- (Вариант 2) Используйте объект> Windows.Foundation.EventHandler<(но потеряйте сведения о типе события). Если вариант 1 недоступен, или если его производительность не является достаточной, то это хороший второй выбор, если потеря сведений о типе допустима. Если вы создаете компонент C# среда выполнения Windows, тип объекта> Windows.Foundation.EventHandler недоступен. Вместо этого этот тип проецируется в System.EventHandler<, поэтому вместо этого следует использовать его.
- (Вариант 3) Создайте собственный прокси-сервер и заглушку для компонента. Этот вариант является наиболее сложным для реализации, но сохраняет сведения о типе и может обеспечить более высокую производительность по сравнению с вариантом 1 в сложных сценариях.
Если вы просто создаете событие в фоновом потоке без использования одного из этих параметров, клиент JavaScript не получит событие.
Общие сведения
Все среда выполнения Windows компоненты и приложения являются основными COM-объектами, независимо от того, какой язык вы используете для их создания. В API Windows большинство компонентов — это гибкие COM-объекты, которые могут взаимодействовать одинаково хорошо с объектами в фоновом потоке и в потоке пользовательского интерфейса. Если com-объект не может быть гибким, он требует вспомогательных объектов, известных как прокси-серверы и заглушки, для взаимодействия с другими com-объектами через границу потока потока пользовательского интерфейса. (В COM-терминах это называется обменом данными между квартирами потоков.)
Большинство объектов в API Windows являются гибкими или имеют прокси-серверы и заглушки. Однако прокси-серверы и заглушки не могут быть созданы для универсальных типов, таких как Windows.Foundation.TypedEventHandler<TSender, TResult> , так как они не являются полными типами, пока не укажите аргумент типа. Это только с клиентами JavaScript, что отсутствие прокси-серверов или заглушки становится проблемой, но если вы хотите, чтобы ваш компонент был доступен для использования из JavaScript, а также из языка C++ или .NET, необходимо использовать один из следующих трех вариантов.
(Вариант 1) Вызов события через CoreDispatcher
События любого определяемого пользователем типа делегата можно отправлять с помощью Windows.UI.Core.CoreDispatcher, и JavaScript сможет получать их. Если вы не уверены, какой вариант следует использовать, попробуйте сначала. Если задержка между запуском события и обработкой событий становится проблемой, попробуйте один из других вариантов.
В следующем примере показано, как использовать CoreDispatcher для создания строго типизированного события. Обратите внимание, что аргумент типа — Toast, а не Object.
public event EventHandler<Toast> ToastCompletedEvent;
private void OnToastCompleted(Toast args)
{
var completedEvent = ToastCompletedEvent;
if (completedEvent != null)
{
completedEvent(this, args);
}
}
public void MakeToastWithDispatcher(string message)
{
Toast toast = new Toast(message);
// Assume you have a CoreDispatcher at class scope.
// Initialize it here, then use it from the background thread.
var window = Windows.UI.Core.CoreWindow.GetForCurrentThread();
m_dispatcher = window.Dispatcher;
Task.Run( () =>
{
if (ToastCompletedEvent != null)
{
m_dispatcher.RunAsync(CoreDispatcherPriority.Normal,
new DispatchedHandler(() =>
{
this.OnToastCompleted(toast);
})); // end m_dispatcher.RunAsync
}
}); // end Task.Run
}
(Вариант 2) Использование объекта> EventHandler<, но потеря сведений о типе
Примечание.
Если вы создаете компонент C# среда выполнения Windows, тип объекта> Windows.Foundation.EventHandler недоступен. Вместо этого этот тип проецируется в System.EventHandler<, поэтому вместо этого следует использовать его.
Другим способом отправки события из фонового потока является использование объекта> Windows.Foundation.EventHandler<в качестве типа события. Windows предоставляет это конкретное экземпляр универсального типа и предоставляет прокси-сервер и заглушку для него. Недостатком является то, что сведения о типе данных о событиях и отправителя теряются. Клиенты C++ и .NET должны знать в документации, к какой типу следует вернуться при получении события. Клиентам JavaScript не нужны исходные сведения о типе. Они находят свойства arg на основе их имен в метаданных.
В этом примере показано, как использовать объект> Windows.Foundation.EventHandler<в C#:
public sealed Class1
{
// Declare the event
public event EventHandler<Object> ToastCompletedEvent;
// Raise the event
public async void MakeToast(string message)
{
Toast toast = new Toast(message);
// Fire the event from a background thread to allow this thread to continue
Task.Run(() =>
{
if (ToastCompletedEvent != null)
{
OnToastCompleted(toast);
}
});
}
private void OnToastCompleted(Toast args)
{
var completedEvent = ToastCompletedEvent;
if (completedEvent != null)
{
completedEvent(this, args);
}
}
}
Это событие используется на стороне JavaScript следующим образом:
toastCompletedEventHandler: function (event) {
var toastType = event.toast.toastType;
document.getElementById("toasterOutput").innerHTML = "<p>Made " + toastType + " toast</p>";
}
(Вариант 3) Создание собственного прокси-сервера и заглушки
Для повышения производительности определяемых пользователем типов событий, имеющих полностью сохраненные сведения о типе, необходимо создать собственные объекты прокси-сервера и заглушки и внедрить их в пакет приложения. Как правило, этот вариант следует использовать только в редких ситуациях, когда ни один из других двух вариантов не является достаточным. Кроме того, нет никаких гарантий, что этот вариант обеспечит лучшую производительность, чем другие два варианта. Фактическая производительность зависит от многих факторов. Используйте профилировщик Visual Studio или другие средства профилирования, чтобы оценить фактическую производительность приложения и определить, является ли событие узким местом.
В остальной части этой статьи показано, как использовать C# для создания базового компонента среда выполнения Windows, а затем использовать C++ для создания библиотеки DLL для прокси-сервера и заглушки, которая позволит JavaScript использовать windows.Foundation.TypedEventHandler<TSender, TResult> событие, вызываемое компонентом в асинхронной операции. (Для создания компонента можно также использовать C++ или Visual Basic. Действия, связанные с созданием прокси-серверов и заглушки, одинаковы.) Это пошаговое руководство основано на создании примера компонента среда выполнения Windows процесса (C++/CX) и помогает объяснить его цели.
В этом пошаговом руководстве есть эти части.
- Здесь вы создадите два основных класса среда выполнения Windows. Один класс предоставляет событие типа Windows.Foundation.TypedEventHandler<TSender, TResult> и другой класс является типом, возвращаемым в JavaScript в качестве аргумента TValue. Эти классы не могут взаимодействовать с JavaScript, пока не завершите дальнейшие действия.
- Это приложение активирует объект основного класса, вызывает метод и обрабатывает событие, вызываемое компонентом среда выполнения Windows.
- Это необходимые средства, создающие классы прокси-сервера и заглушки.
- Затем вы используете IDL-файл для создания исходного кода C для прокси-сервера и заглушки.
- Зарегистрируйте объекты прокси-заглушки, чтобы среда выполнения COM могли их найти и ссылаться на библиотеку DLL прокси-заглушки в проекте приложения.
Создание компонента среда выполнения Windows
В Visual Studio в строке меню выберите "Файл > нового проекта". В диалоговом окне "Новый проект" разверните универсальные окна JavaScript > и выберите пустое приложение. Присвойте проекту имя Тостерпликации и нажмите кнопку "ОК ".
Добавьте компонент среда выполнения Windows C# в решение: в Обозреватель решений откройте контекстное меню решения и нажмите кнопку "Добавить > новый проект". Разверните Microsoft Store Visual C# > и выберите компонент среда выполнения Windows. Назовите проект ТостерComponent и нажмите кнопку "ОК ". ТостерComponent будет корневым пространством имен для компонентов, которые вы создадите в последующих шагах.
В Обозреватель решений откройте контекстное меню решения и выберите пункт "Свойства". В диалоговом окне "Страницы свойств" выберите "Свойства конфигурации" в левой области, а затем в верхней части диалогового окна установите для параметра "Конфигурация" значение "Отладка" и "Платформа" значение x86, x64 или ARM. Нажмите кнопку ОК.
Важной платформы = любой ЦП не будет работать, так как он недействителен для библиотеки DLL Win32 машинного кода, которую вы добавите в решение позже.
В Обозреватель решений переименуйте class1.cs на ToasterComponent.cs, чтобы оно соответствовало имени проекта. Visual Studio автоматически переименовывает класс в файле, чтобы соответствовать новому имени файла.
В файле .cs добавьте директиву using для пространства имен Windows.Foundation, чтобы перенести TypedEventHandler в область.
Если требуется прокси-серверы и заглушки, компонент должен использовать интерфейсы для предоставления его общедоступных участников. В ToasterComponent.cs определите интерфейс для тостера, а другой для тостера, который производит тостер.
Примечание. В C# этот шаг можно пропустить. Вместо этого сначала создайте класс, а затем откройте контекстное меню и выберите "Рефакторинг > извлечения интерфейса". В созданном коде вручную предоставьте интерфейсы общедоступной доступности.
public interface IToaster
{
void MakeToast(String message);
event TypedEventHandler<Toaster, Toast> ToastCompletedEvent;
}
public interface IToast
{
String ToastType { get; }
}
Интерфейс IToast содержит строку, которую можно получить для описания типа всплывающего уведомления. Интерфейс IToaster имеет метод для создания всплывающего уведомления, и событие, указывающее, что тост сделан. Так как это событие возвращает определенную часть (т. е. тип) всплывающего уведомления, она называется типизированным событием.
Далее нам нужны классы, реализующие эти интерфейсы, и открытые и запечатанные, чтобы они были доступны из приложения JavaScript, которое вы будете программированы позже.
public sealed class Toast : IToast
{
private string _toastType;
public string ToastType
{
get
{
return _toastType;
}
}
internal Toast(String toastType)
{
_toastType = toastType;
}
}
public sealed class Toaster : IToaster
{
public event TypedEventHandler<Toaster, Toast> ToastCompletedEvent;
private void OnToastCompleted(Toast args)
{
var completedEvent = ToastCompletedEvent;
if (completedEvent != null)
{
completedEvent(this, args);
}
}
public void MakeToast(string message)
{
Toast toast = new Toast(message);
// Fire the event from a thread-pool thread to enable this thread to continue
Windows.System.Threading.ThreadPool.RunAsync(
(IAsyncAction action) =>
{
if (ToastCompletedEvent != null)
{
OnToastCompleted(toast);
}
});
}
}
В приведенном выше коде мы создадим всплывающее уведомление, а затем создадим рабочий элемент пула потоков, чтобы запустить уведомление. Хотя интегрированная среда разработки может предложить применить ключевое слово await к асинхронном вызову, в этом случае не требуется, так как метод не выполняет никаких действий, зависящих от результатов операции.
Примечание . Асинхронный вызов в предыдущем коде использует ThreadPool.RunAsync исключительно для демонстрации простого способа запуска события в фоновом потоке. Этот конкретный метод можно написать, как показано в следующем примере, и он будет работать нормально, так как планировщик задач .NET автоматически маршалирует асинхронные и ожидающий вызовы обратно в поток пользовательского интерфейса.
public async void MakeToast(string message)
{
Toast toast = new Toast(message)
await Task.Delay(new Random().Next(1000));
OnToastCompleted(toast);
}
Если вы создаете проект сейчас, он должен выполняться чисто.
Программирование приложения JavaScript
Теперь мы можем добавить кнопку в приложение JavaScript, чтобы он использовал класс, который мы только что определили, чтобы сделать всплывающее уведомление. Прежде чем это сделать, мы должны добавить ссылку на проект ТостерКомпонент, который мы только что создали. В Обозреватель решений откройте контекстное меню проекта ТостерApplication, нажмите кнопку "Добавить > ссылки", а затем нажмите кнопку "Добавить новую ссылку". В диалоговом окне "Добавить ссылку" в области слева в разделе "Решение" выберите проект компонента, а затем в средней области выберите "ТостерКомпонент". Нажмите кнопку ОК.
В Обозреватель решений откройте контекстное меню проекта ТостерApplication, а затем выберите "Задать в качестве запускаемого проекта".
В конце файла default.js добавьте пространство имен, чтобы содержать функции для вызова компонента и его вызова. Пространство имен будет иметь две функции, один для выполнения всплывающих элементов и один для обработки события всплывающего завершения. Реализация makeToast создает объект Тостера, регистрирует обработчик событий и делает всплывающее уведомление. До сих пор обработчик событий не делает много, как показано здесь:
WinJS.Namespace.define("ToasterApplication"), {
makeToast: function () {
var toaster = new ToasterComponent.Toaster();
//toaster.addEventListener("ontoastcompletedevent", ToasterApplication.toastCompletedEventHandler);
toaster.ontoastcompletedevent = ToasterApplication.toastCompletedEventHandler;
toaster.makeToast("Peanut Butter");
},
toastCompletedEventHandler: function(event) {
// The sender of the event (the delegate's first type parameter)
// is mapped to event.target. The second argument of the delegate
// is contained in event, which means in this case event is a
// Toast class, with a toastType string.
var toastType = event.toastType;
document.getElementById('toastOutput').innerHTML = "<p>Made " + toastType + " toast</p>";
},
});
Функция makeToast должна быть подключена к кнопке. Обновите default.html, чтобы включить кнопку и некоторое пространство, чтобы вывести результат выполнения всплывающего уведомления:
<body>
<h1>Click the button to make toast</h1>
<button onclick="ToasterApplication.makeToast()">Make Toast!</button>
<div id="toasterOutput">
<p>No Toast Yet...</p>
</div>
</body>
Если бы мы не использовали TypedEventHandler, теперь мы могли бы запустить приложение на локальном компьютере и нажать кнопку, чтобы сделать всплывающее уведомление. Но в нашем приложении ничего не происходит. Чтобы узнать, почему давайте отладим управляемый код, который запускает toastCompletedEvent. Остановите проект, а затем в строке меню выберите свойства отладочного приложения тостера>. Измените тип отладчика только на управляемый. Снова в строке меню выберите "Отладка > исключений", а затем выберите исключения среды CLR.
Теперь запустите приложение и нажмите кнопку всплывающего уведомления. Отладчик перехватывает недопустимое исключение приведения. Хотя это не очевидно из сообщения, это исключение происходит, так как прокси-серверы отсутствуют для этого интерфейса.
Первым шагом при создании прокси-сервера и заглушки для компонента является добавление уникального идентификатора или GUID в интерфейсы. Однако формат GUID, используемый для использования, отличается в зависимости от того, кодируете ли вы в C#, Visual Basic или другом языке .NET или в C++.
Создание идентификаторов GUID для интерфейсов компонента (C# и других языков .NET)
В строке меню выберите "Сервис > создания GUID". В диалоговом окне выберите 5. [Guid("xxxxx-xxxx... xxxx")]. Нажмите кнопку "Создать GUID" и нажмите кнопку "Копировать".
Вернитесь к определению интерфейса и вставьте новый GUID непосредственно перед интерфейсом IToaster, как показано в следующем примере. (Не используйте GUID в примере. Каждый уникальный интерфейс должен иметь собственный GUID.)
[Guid("FC198F74-A808-4E2A-9255-264746965B9F")]
public interface IToaster...
Добавьте директиву using для пространства имен System.Runtime.InteropServices.
Повторите эти действия для интерфейса IToast.
Создание идентификаторов GUID для интерфейсов компонента (C++)
В строке меню выберите "Сервис > создания GUID". В диалоговом окне выберите 3. статический констант GUID структуры = {...}. Нажмите кнопку "Создать GUID" и нажмите кнопку "Копировать".
Вставьте GUID непосредственно перед определением интерфейса IToaster. После вставки GUID должен выглядеть следующим образом. (Не используйте GUID в примере. Каждый уникальный интерфейс должен иметь собственный GUID.)
// {F8D30778-9EAF-409C-BCCD-C8B24442B09B}
static const GUID <<name>> = { 0xf8d30778, 0x9eaf, 0x409c, { 0xbc, 0xcd, 0xc8, 0xb2, 0x44, 0x42, 0xb0, 0x9b } };
Добавьте директиву using для Windows.Foundation.Metadata, чтобы перенести GuidAttribute в область.
Теперь вручную преобразуйте GUID const в guidAttribute, чтобы он был отформатирован, как показано в следующем примере. Обратите внимание, что фигурные скобки заменяются скобками и скобками, а запятая запятая удаляется.
// {E976784C-AADE-4EA4-A4C0-B0C2FD1307C3}
[GuidAttribute(0xe976784c, 0xaade, 0x4ea4, 0xa4, 0xc0, 0xb0, 0xc2, 0xfd, 0x13, 0x7, 0xc3)]
public interface IToaster
{...
Повторите эти действия для интерфейса IToast.
Теперь, когда интерфейсы имеют уникальные идентификаторы, мы можем создать IDL-файл, предоставив winmd-файл в средство командной строки winmdidl, а затем создадим исходный код C для прокси-сервера и заглушки, предоставив этот IDL-файл в средство командной строки MIDL. Visual Studio делает это для нас, если мы создадим события после сборки, как показано на следующих шагах.
Создание исходного кода прокси-сервера и заглушки
Чтобы добавить настраиваемое событие после сборки, в Обозреватель решений откройте контекстное меню проекта ТостерКомпонент и выберите пункт "Свойства". В левой области страниц свойств выберите "События сборки" и нажмите кнопку "Изменить после сборки". Добавьте следующие команды в командную строку после сборки. (Пакетный файл необходимо вызвать сначала, чтобы задать переменные среды, чтобы найти средство winmdidl.)
call "$(DevEnvDir)..\..\vc\vcvarsall.bat" $(PlatformName)
winmdidl /outdir:output "$(TargetPath)"
midl /metadata_dir "%WindowsSdkDir%References\CommonConfiguration\Neutral" /iid "$(ProjectDir)$(TargetName)_i.c" /env win32 /h "$(ProjectDir)$(TargetName).h" /winmd "Output\$(TargetName).winmd" /W1 /char signed /nologo /winrt /dlldata "$(ProjectDir)dlldata.c" /proxy "$(ProjectDir)$(TargetName)_p.c" "Output\$(TargetName).idl"
Важно, чтобы конфигурация проекта ARM или x64 изменила параметр MIDL /env на x64 или arm32.
Чтобы убедиться, что IDL-файл повторно создается при каждом изменении winmd-файла, измените событие после сборки на то, когда сборка обновляет выходные данные проекта. Страница свойств "События сборки" должна выглядеть следующим образом:
Перестройте решение для создания и компиляции IDL.
Вы можете убедиться, что MIDL правильно скомпилировано решение, найдите ТостерComponent.h, ToasterComponent_i.c, ToasterComponent_p.c и dlldata.c в каталоге проекта ТостерComponent.
Компиляция прокси-сервера и заглушки в библиотеку DLL
Теперь, когда у вас есть необходимые файлы, их можно скомпилировать для создания библиотеки DLL, которая является файлом C++. Чтобы сделать это как можно проще, добавьте новый проект для поддержки создания прокси-серверов. Откройте контекстное меню для решения "ТостерApplication", а затем нажмите кнопку "Добавить > новый проект". В левой области диалогового окна "Новый проект" разверните универсальные окна Visual C++ > для Windows>, а затем в средней области выберите библиотеку DLL (приложения UWP). (Обратите внимание, что это не проект компонента C++ среда выполнения Windows.) Назовите прокси проекта и нажмите кнопку "ОК". Эти файлы будут обновлены событиями после сборки при изменении чего-либо в классе C#.
По умолчанию проект прокси-серверов создает файлы заголовка H и файлы C++ .cpp. Так как библиотека DLL создается из файлов, созданных из MIDL, файлы H и .cpp не требуются. В Обозреватель решений откройте контекстное меню для них, нажмите кнопку "Удалить", а затем подтвердите удаление.
Теперь, когда проект пуст, можно добавить файлы, созданные MIDL. Откройте контекстное меню проекта прокси-серверов и нажмите кнопку "Добавить > существующий элемент". В диалоговом окне перейдите к каталогу проекта ТостерКомпонент и выберите следующие файлы: ТостерComponent.h, ToasterComponent_i.c, ToasterComponent_p.c и dlldata.c. Нажмите кнопку Добавить .
В проекте прокси-серверов создайте def-файл для определения экспортов DLL, описанных в dlldata.c. Откройте контекстное меню проекта и нажмите кнопку "Добавить > новый элемент". В левой области диалогового окна выберите "Код", а затем в средней области выберите файл определения модуля. Назовите файл proxies.def и нажмите кнопку "Добавить ". Откройте этот DEF-файл и измените его, чтобы включить EXPORTS, определенные в dlldata.c:
EXPORTS
DllCanUnloadNow PRIVATE
DllGetClassObject PRIVATE
Если вы создадите проект сейчас, он завершится ошибкой. Чтобы правильно скомпилировать этот проект, необходимо изменить способ компиляции и связывания проекта. В Обозреватель решений откройте контекстное меню для проекта прокси-серверов и выберите пункт "Свойства". Измените страницы свойств следующим образом.
В левой области выберите препроцессор C/C++>, а затем в правой области выберите "Определения препроцессора", нажмите кнопку со стрелкой вниз и нажмите кнопку "Изменить". Добавьте эти определения в поле:
WIN32;_WINDOWS
В разделе Предварительно скомпилированные заголовки C/C++ > измените предварительно скомпилированные заголовки на "Не использовать предварительно скомпилированные заголовки", а затем нажмите кнопку "Применить".
В разделе "Общие компоновщики>" измените "Игнорировать библиотеку импорта" на "Ye" и нажмите кнопку "Применить".
В разделе "Входные данные компоновщика>" выберите дополнительные зависимости, нажмите кнопку стрелки вниз и нажмите кнопку "Изменить". Добавьте этот текст в поле:
rpcrt4.lib;runtimeobject.lib
Не вставьте эти libs непосредственно в строку списка. Используйте поле "Изменить", чтобы убедиться, что MSBuild в Visual Studio будет поддерживать правильные дополнительные зависимости.
После внесения этих изменений нажмите кнопку "ОК" в диалоговом окне "Страницы свойств".
Затем примите зависимость от проекта ТостерComponent. Это гарантирует, что тостер будет создаваться до сборки прокси-проекта. Это необходимо, так как проект Тостера отвечает за создание файлов для создания прокси-сервера.
Откройте контекстное меню для проекта прокси-серверов и выберите "Зависимости проекта". Установите флажки, чтобы указать, что проект прокси-серверов зависит от проекта ТостерКомпонент, чтобы убедиться, что Visual Studio создает их в правильном порядке.
Убедитесь, что решение правильно строится, выбрав "Создать > перестроение решения" в строке меню Visual Studio.
Регистрация прокси-сервера и заглушки
В проекте ТостерApplication откройте контекстное меню для package.appxmanifest и нажмите кнопку "Открыть с". В диалоговом окне "Открыть с помощью" выберите текстовый редактор XML и нажмите кнопку "ОК ". Мы вставляем в некоторый XML-код, предоставляющий регистрацию расширения windows.activeableClass.proxyStub и основанные на идентификаторах GUID в прокси-сервере. Чтобы найти идентификаторы GUID для использования в appxmanifest-файле, откройте файл ToasterComponent_i.c. Найдите записи, похожие на те, которые приведены в следующем примере. Кроме того, обратите внимание на определения для IToast, IToaster и третий интерфейс — типизированный обработчик событий с двумя параметрами: тостер и тостер. Это соответствует событию, определенному в классе Тостера. Обратите внимание, что идентификаторы GUID для IToast и IToaster соответствуют идентификаторам GUID, определенным в интерфейсах в файле C#. Так как типизированный интерфейс обработчика событий создается автоматически, GUID для этого интерфейса также создается автоматически.
MIDL_DEFINE_GUID(IID, IID___FITypedEventHandler_2_ToasterComponent__CToaster_ToasterComponent__CToast,0x1ecafeff,0x1ee1,0x504a,0x9a,0xf5,0xa6,0x8c,0x6f,0xb2,0xb4,0x7d);
MIDL_DEFINE_GUID(IID, IID___x_ToasterComponent_CIToast,0xF8D30778,0x9EAF,0x409C,0xBC,0xCD,0xC8,0xB2,0x44,0x42,0xB0,0x9B);
MIDL_DEFINE_GUID(IID, IID___x_ToasterComponent_CIToaster,0xE976784C,0xAADE,0x4EA4,0xA4,0xC0,0xB0,0xC2,0xFD,0x13,0x07,0xC3);
Теперь мы копируем идентификаторы GUID, вставьте их в package.appxmanifest в узел, который мы добавляем и именуем расширения, а затем переформатируйте их. Запись манифеста похожа на следующий пример, но опять же не забудьте использовать собственные идентификаторы GUID. Обратите внимание, что GUID ClassId в XML совпадает с идентификатором ITypedEventHandler2. Это связано с тем, что этот GUID является первым, который указан в ToasterComponent_i.c. Идентификаторы GUID здесь не учитывает регистр. Вместо ручного переформатирования идентификаторов GUID для IToast и IToaster можно вернуться в определения интерфейса и получить значение GuidAttribute, которое имеет правильный формат. В C++в примечании имеется правильно отформатированный GUID. В любом случае необходимо вручную переформатировать GUID, который используется как для ClassId, так и для обработчика событий.
<Extensions> <!--Use your own GUIDs!!!-->
<Extension Category="windows.activatableClass.proxyStub">
<ProxyStub ClassId="1ecafeff-1ee1-504a-9af5-a68c6fb2b47d">
<Path>Proxies.dll</Path>
<Interface Name="IToast" InterfaceId="F8D30778-9EAF-409C-BCCD-C8B24442B09B"/>
<Interface Name="IToaster" InterfaceId="E976784C-AADE-4EA4-A4C0-B0C2FD1307C3"/>
<Interface Name="ITypedEventHandler_2_ToasterComponent__CToaster_ToasterComponent__CToast" InterfaceId="1ecafeff-1ee1-504a-9af5-a68c6fb2b47d"/>
</ProxyStub>
</Extension>
</Extensions>
Вставьте XML-узел extensions в качестве прямого дочернего элемента узла пакета и однорангового узла, например узла Resources.
Прежде чем двигаться дальше, важно убедиться в том, что:
- Идентификатор класса ProxyStub имеет первый GUID в файле ToasterComponent_i.c. Используйте первый GUID, определенный в этом файле для classId. (Это может быть так же, как GUID для ITypedEventHandler2.)
- Путь — это относительный путь к пакету двоичного файла прокси-сервера. (В этом пошаговом руководстве proxies.dll находится в той же папке, что и ТостерApplication.winmd.)
- Идентификаторы GUID находятся в правильном формате. (Это легко получить неправильно.)
- Идентификаторы интерфейса в манифесте соответствуют идентификаторам IID в файле ToasterComponent_i.c.
- Имена интерфейсов уникальны в манифесте. Так как они не используются системой, вы можете выбрать значения. Рекомендуется выбирать имена интерфейсов, которые четко соответствуют определенным интерфейсам. Для созданных интерфейсов имена должны указывать на созданные интерфейсы. Файл ToasterComponent_i.c можно использовать для создания имен интерфейсов.
Если вы попытаетесь запустить решение сейчас, вы получите ошибку, которая proxies.dll не является частью полезных данных. Откройте контекстное меню папки "Ссылки " в проекте "ТостерApplication", а затем нажмите кнопку "Добавить ссылку". Установите флажок рядом с проектом прокси-серверов. Кроме того, установите флажок рядом с ТостерКомпонентом. Нажмите кнопку ОК.
Теперь проект должен быть построен. Запустите проект и убедитесь, что вы можете сделать всплывающее уведомление.