Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом разделе мы рассмотрим, как с помощью C#/WinRT создавать проекционные сборки C# .NET (или сборки для взаимодействия) из Windows Runtime компонентов C++/WinRT и распространять их в виде пакетов NuGet для приложений .NET.
В .NET 6 и более поздних версиях чтение файлов метаданных Windows (WinMD) больше не поддерживается (см. удаление встроенной поддержки WinRT из .NET). Вместо этого можно использовать средство C#/WinRT для создания проекционной сборки любого файла WinMD, что затем позволяет приложениям .NET использовать компоненты WinRT. Узел проекции также называется узлом взаимодействия. В этом пошаговом руководстве показано, как выполнить следующие действия.
- Используйте пакет C#/WinRT для создания проекции C# из компонента C++/WinRT.
- Распространите компонент вместе с сборкой проекции как пакет NuGet.
- Подключите пакет NuGet в консольном приложении .NET.
Предпосылки
В этом пошаговом руководстве и соответствующем примере требуются следующие средства и компоненты:
- Visual Studio 2022 (или Visual Studio 2019) с установленной рабочей нагрузкой разработки универсальной платформы Windows. В сведениях об установке>разработки универсальной платформы Windows проверьте инструменты универсальной платформы Windows (v14x).
- пакет SDK для .NET 6.0 или более поздней версии.
только Visual Studio 2019. Расширение VSIX для C++/WinRT, которое предоставляет шаблоны проектов C++/WinRT в Visual Studio. Шаблоны проектов встроены в Visual Studio 2022.
В этом пошаговом руководстве мы будем использовать Visual Studio 2022 и .NET 6.
Это важно
Кроме того, вам потребуется скачать или клонировать пример кода для этого раздела из примера проекции C#/WinRT на GitHub. Перейдите CsWinRTи нажмите зеленую кнопку code, чтобы получить URL-адрес git clone
. Обязательно прочитайте файл README.md для примера.
Создание простого компонента среды выполнения Windows C++/WinRT
Чтобы следовать этому пошаговому руководству, у вас должен быть компонент среды выполнения Windows C++/WinRT (WRC), на основе которого будет создаваться сборка проекции C#.
В этом пошаговом руководстве используется SimpleMathComponent WRC из примера проекции C#/WinRT на GitHub, который вы уже скачали или клонировали. SimpleMathComponent был создан из компонента среды выполнения Windows (C++/WinRT), который является шаблоном проекта Visual Studio (доступен в Visual Studio 2022 или через расширение C++/WinRT VSIX).
Чтобы открыть проект
Код в этом проекте предоставляет функциональные возможности для основных математических операций, показанных в файле заголовка ниже.
// SimpleMath.h
...
namespace winrt::SimpleMathComponent::implementation
{
struct SimpleMath: SimpleMathT<SimpleMath>
{
SimpleMath() = default;
double add(double firstNumber, double secondNumber);
double subtract(double firstNumber, double secondNumber);
double multiply(double firstNumber, double secondNumber);
double divide(double firstNumber, double secondNumber);
};
}
Вы можете подтвердить, что для проекта компонента C++/WinRT Windows Runtime SimpleMathComponent свойство Windows Desktop Compatible установлено в значение Да. Для этого в свойствах проекта
Для получения более подробных сведений о создании компонента C++/WinRT и генерации файла WinMD см. раздел «Компоненты среды выполнения Windows с помощью C++/WinRT».
Замечание
Если вы реализуете IInspectable::GetRuntimeClassName в компоненте, должен вернуть допустимое имя класса WinRT. Так как C#/WinRT использует строку имени класса для взаимодействия, неправильное имя класса среды выполнения вызовет InvalidCastException.
Добавьте проект проекции в решение компонента
Во-первых, при использовании решения CppWinRTComponentProjectionSample , который по-прежнему открыт в Visual Studio, удалите проект SimpleMathProjection из этого решения. Затем удалите из файловой системы папку SimpleMathProjection (или переименуйте ее, если вы предпочитаете). Эти действия необходимы, чтобы вы могли следовать этому пошаговому руководству.
Добавьте в решение новый проект библиотеки C#.
- В обозревателе решений щелкните правой кнопкой мыши на узле решения и выберите Добавить>Новый проект.
- В диалоговом окне Добавление нового проекта в поле поиска введите Библиотеку классов. Выберите C# в списке языков и выберите Windows из списка платформ. Выберите шаблон проекта C#, который просто называется Библиотека классов (без префиксов и суффиксов), и нажмите Далее.
- Назовите новый проект SimpleMathProjection. Расположение должно быть уже задано в той же
\CsWinRT\src\Samples\NetProjectionSample
папке, в которой находится папка SimpleMathComponent. Пожалуйста, подтвердите это. Затем нажмите Далее. - На странице Дополнительные сведения выберите .NET 6.0 (долгосрочная поддержка), а затем выберите Создать.
Удалите файл-заглушку Class1.cs из проекта.
Чтобы установить пакет NuGet C#/WinRT, выполните приведенные ниже действия.
- В обозревателе решений щелкните правой кнопкой мыши проект SimpleMathProjection и выберите пункт "Управление пакетами NuGet".
- На вкладке Обзор введите или вставьте Microsoft.Windows.CsWinRT в поле поиска, в результатах поиска выберите элемент с последней версией, а затем щелкните Установить, чтобы установить пакет в проект SimpleMathProjection.
Добавьте в проект SimpleMathProjection ссылку на проект SimpleMathComponent. В обозревателе решений
щелкните правой кнопкой мыши узел зависимостей в узле проекта SimpleMathProjectionSimpleMathProjection, выберите Добавить ссылку на проект и выберите проектSimpleMathComponent OK .
Пока не пытайтесь создать проект. Мы будем делать это позже.
На данный момент ваш обозреватель решений должен выглядеть примерно так (ваши номера версий будут отличаться).
Обозреватель решений
Сборка проектов из исходного кода
Для решения CppWinRTComponentProjectionSample в примере проекции C#/WinRT (который вы скачали или клонировали из GitHub и теперь открыли) расположение выходных данных сборки настраивается с помощью файла Directory.Build.props для сборки вне исходной папки. Это означает, что файлы из выходных данных сборки создаются за пределами исходной папки. Рекомендуем компилировать из исходного кода при использовании инструмента C#/WinRT. Это предотвращает непреднамеренное получение всех *.cs файлов в корневом каталоге проекта, что может привести к ошибкам повторяющегося типа (например, при компиляции для нескольких конфигураций и платформ).
Несмотря на то что это уже настроено для решения CppWinRTComponentProjectionSample, выполните приведенные ниже действия, чтобы попрактиковаться в настройке самостоятельно.
Чтобы настроить решение для сборки из источника, выполните следующие действия.
Убедитесь, что решение CppWinRTComponentProjectionSample остается открытым, щелкните правой кнопкой мыши на узле решения и выберите Добавить>Новый элемент. Выберите элемент XML-файла и назовите его Directory.Build.props (без
.xml
расширения). Нажмите кнопку "Да" , чтобы перезаписать существующий файл.Замените содержимое Directory.Build.props конфигурацией ниже.
<Project> <PropertyGroup> <BuildOutDir>$([MSBuild]::NormalizeDirectory('$(SolutionDir)', '_build', '$(Platform)', '$(Configuration)'))</BuildOutDir> <OutDir>$([MSBuild]::NormalizeDirectory('$(BuildOutDir)', '$(MSBuildProjectName)', 'bin'))</OutDir> <IntDir>$([MSBuild]::NormalizeDirectory('$(BuildOutDir)', '$(MSBuildProjectName)', 'obj'))</IntDir> </PropertyGroup> </Project>
Сохраните и закройте файл Directory.Build.props .
Изменение файла проекта для выполнения C#/WinRT
Прежде чем вызвать cswinrt.exe
средство для создания сборки проекции, необходимо сначала изменить файл проекта, чтобы указать несколько свойств проекта.
В обозревателе решений дважды щелкните узел SimpleMathProjection, чтобы открыть файл проекта в редакторе.
Обновите элемент
TargetFramework
, чтобы использовать определенную версию Windows SDK. Это добавляет зависимости сборки, которые необходимы для поддержки интероперабельности и проекции. Этот пример предназначен для версии Windows SDK net6.0-windows10.0.19041.0 (также известна как Windows 10, версия 2004). Укажите для элементаPlatform
, чтобы результирующую проекционную сборку можно использовать для любой архитектуры приложения. Чтобы разрешить ссылки на приложения для поддержки более ранних версий пакета SDK для Windows, можно также задатьTargetPlatformMinimumVersion
свойство.<PropertyGroup> <TargetFramework>net8.0-windows10.0.19041.0</TargetFramework> <!-- Set Platform to AnyCPU to allow consumption of the projection assembly from any architecture. --> <Platform>AnyCPU</Platform> </PropertyGroup>
Замечание
В этом пошаговом руководстве и соответствующем примере кода решение создается для x64 и Release. Обратите внимание, что проект SimpleMathProjection настроен для сборки под AnyCPU для всех конфигураций архитектуры решения.
Добавьте второй
PropertyGroup
элемент (сразу после первого), который задает несколько свойств C#/WinRT.<PropertyGroup> <CsWinRTIncludes>SimpleMathComponent</CsWinRTIncludes> <CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir> </PropertyGroup>
Ниже приведены некоторые сведения о параметрах в этом примере:
- Свойство
CsWinRTIncludes
указывает, какие пространства имен необходимо проецировать. - Свойство
CsWinRTGeneratedFilesDir
задает выходной каталог, в котором создаются исходные файлы проекции. Это свойство имеет значениеOutDir
, определенное в Directory.Build.props из приведенного выше раздела.
- Свойство
Сохраните и закройте файл SimpleMathProjection.csproj и щелкните, чтобы перезагрузить проекты при необходимости.
Создание пакета NuGet с проекцией
Чтобы распространить сборку проекции для разработчиков приложений .NET, вы можете автоматически создать пакет NuGet при создании решения, добавив дополнительные свойства проекта. Для целевых объектов .NET пакет NuGet должен включать сборку проекции и сборку реализации из компонента.
Чтобы добавить файл спецификации NuGet (
.nuspec
) в проект SimpleMathProjection , выполните приведенные ниже действия.- В обозревателе решений щелкните правой кнопкой мыши узел SimpleMathProjection, выберите Добавить>новую папкуи назовите папку nuget.
- Щелкните правой кнопкой мыши папку nuget, выберите Добавить>Новый элемент, выберите XML-файли назовите его SimpleMathProjection.nuspec.
В обозревателе решений дважды щелкните узел SimpleMathProjection, чтобы открыть файл проекта в редакторе. Добавьте следующую группу свойств в открытый файл SimpleMathProjection.csproj (сразу после двух существующих
PropertyGroup
элементов), чтобы автоматически создать пакет. Эти свойства указываютNuspecFile
и каталог для создания пакета NuGet.<PropertyGroup> <GeneratedNugetDir>.\nuget\</GeneratedNugetDir> <NuspecFile>$(GeneratedNugetDir)SimpleMathProjection.nuspec</NuspecFile> <OutputPath>$(GeneratedNugetDir)</OutputPath> <GeneratePackageOnBuild>true</GeneratePackageOnBuild> </PropertyGroup>
Замечание
Если вы предпочитаете создавать пакет отдельно, можно также запустить
nuget.exe
средство из командной строки. Дополнительные сведения о создании пакета NuGet см. в статье "Создание пакета с помощью интерфейса командной строки nuget.exe".Откройте файл SimpleMathProjection.nuspec , чтобы изменить свойства создания пакета и вставьте следующий код. Приведенный ниже фрагмент кода является примером спецификации NuGet для распространения SimpleMathComponent на несколько целевых платформ. Обратите внимание, что сборка проекции, SimpleMathProjection.dll, предусмотрена вместо SimpleMathComponent.winmd для целевого
lib\net6.0-windows10.0.19041.0\SimpleMathProjection.dll
. Это поведение ново в .NET 6 и более поздних версиях и активируется C#/WinRT. Сборка реализации,SimpleMathComponent.dll
, должна быть также распространена и загружена в процессе выполнения.<?xml version="1.0" encoding="utf-8"?> <package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd"> <metadata> <id>SimpleMathComponent</id> <version>0.1.0-prerelease</version> <authors>Contoso Math Inc.</authors> <description>A simple component with basic math operations</description> <dependencies> <group targetFramework="net6.0-windows10.0.19041.0" /> <group targetFramework=".NETCoreApp3.0" /> <group targetFramework="UAP10.0" /> <group targetFramework=".NETFramework4.6" /> </dependencies> </metadata> <files> <!--Support .NET 6, .NET Core 3, UAP, .NET Framework 4.6, C++ --> <!--Architecture-neutral assemblies--> <file src="..\..\_build\AnyCPU\Release\SimpleMathProjection\bin\SimpleMathProjection.dll" target="lib\net6.0-windows10.0.19041.0\SimpleMathProjection.dll" /> <file src="..\..\_build\x64\Release\SimpleMathComponent\bin\SimpleMathComponent\SimpleMathComponent.winmd" target="lib\netcoreapp3.0\SimpleMathComponent.winmd" /> <file src="..\..\_build\x64\Release\SimpleMathComponent\bin\SimpleMathComponent\SimpleMathComponent.winmd" target="lib\uap10.0\SimpleMathComponent.winmd" /> <file src="..\..\_build\x64\Release\SimpleMathComponent\bin\SimpleMathComponent\SimpleMathComponent.winmd" target="lib\net46\SimpleMathComponent.winmd" /> <!--Architecture-specific implementation DLLs should be copied into RID-relative folders--> <file src="..\..\_build\x64\Release\SimpleMathComponent\bin\SimpleMathComponent\SimpleMathComponent.dll" target="runtimes\win10-x64\native\SimpleMathComponent.dll" /> <!--To support x86 and Arm64, build SimpleMathComponent for those other architectures and uncomment the entries below.--> <!--<file src="..\..\_build\Win32\Release\SimpleMathComponent\bin\SimpleMathComponent\SimpleMathComponent.dll" target="runtimes\win10-x86\native\SimpleMathComponent.dll" />--> <!--<file src="..\..\_build\arm64\Release\SimpleMathComponent\bin\SimpleMathComponent\SimpleMathComponent.dll" target="runtimes\win10-arm64\native\SimpleMathComponent.dll" />--> </files> </package>
Замечание
SimpleMathComponent.dll, сборка реализации компонента зависит от архитектуры. Если вы поддерживаете другие платформы (например, x86 или Arm64), сначала необходимо создать SimpleMathComponent для нужных платформ и добавить эти файлы сборок в соответствующую папку , связанную с RID. Сборка проекции SimpleMathProjection.dll и компонент SimpleMathComponent.winmd являются нейтральными по архитектуре.
Сохраните и закройте только что измененные файлы.
Создание решения для создания проекции и пакета NuGet
Перед созданием решения обязательно проверьте параметры Configuration Manager
На этом этапе можно создать решение. Щелкните правой кнопкой мыши на узле в дереве решений и выберите Сборка решения. Сначала будет построен проект SimpleMathComponent , а затем проект SimpleMathProjection . Сборка компонента WinMD и реализация (SimpleMathComponent.winmd и SimpleMathComponent.dll), исходные файлы проекции и сборка проекции (SimpleMathProjection.dll), будут созданы в каталоге выходных данных _build. Вы также сможете просмотреть созданный пакет NuGet SimpleMathComponent0.1.0-prerelease.nupkg в папке \SimpleMathProjection\nuget .
Это важно
Если указанные выше файлы не создаются, создайте решение во второй раз. Вам также может потребоваться закрыть и повторно открыть решение перед повторной сборкой.
Возможно, потребуется закрыть и повторно открыть решение для отображения .nupkg
в Visual Studio, как показано (или просто выбрать, а затем отменить выбор показать все файлы).
Обозреватель решений
Ссылка на пакет NuGet в консольном приложении C# .NET 6
Чтобы использовать SimpleMathComponent из проекта .NET, можно просто добавить в новый .NET проект ссылку на пакет NuGet SimpleMathComponent0.1.0-prerelease.nupkg, созданный в предыдущем разделе. Ниже показано, как это сделать, создав простое консольное приложение в отдельном решении.
Выполните приведенные ниже действия, чтобы создать новое решение, содержащее проект консольного приложения C# (создание этого проекта в новом решении позволяет самостоятельно восстановить пакет SimpleMathComponent NuGet).
Это важно
Мы создадим этот проект консольного приложения
в папке , которую вы найдете в вашей скачанной или клонированной копии примера проекции C#/WinRT .- В новом экземпляре Visual Studio выберите File>New>Project.
- В диалоговом окне Создание нового проекта найдите шаблон проекта Консольное приложение. Выберите шаблон проекта C#, который называется просто Консольное приложение (без префиксов и суффиксов) и нажмите Далее. Если вы используете Visual Studio 2019, шаблон проекта Консольного Приложения.
- Назовите новый проект SampleConsoleApp, задайте его расположение в той же
\CsWinRT\src\Samples\NetProjectionSample
папке, в которую находятся папки SimpleMathComponent и SimpleMathProjection , и нажмите кнопку "Далее". - На странице Дополнительные сведения выберите .NET 6.0 (долгосрочная поддержка), а затем выберите Создать.
В обозревателе решений дважды щелкните узел SampleConsoleApp, чтобы открыть файл проекта SampleConsoleApp.csproj и изменить
TargetFramework
свойства, чтобы они выглядели, как показано в следующем списке.Platform
Добавьте элементPlatform
, если его там нет.<PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net6.0-windows10.0.19041.0</TargetFramework> <Platform>x64</Platform> </PropertyGroup>
С оставленным открытым файлом проекта SampleConsoleApp.csproj мы далее добавим в проект SampleConsoleApp ссылку на пакет NuGet SimpleMathComponent. Чтобы восстановить SimpleMathComponent NuGet при создании проекта, можно использовать свойство
RestoreSources
с путем к папке nuget в решении компонента. Скопируйте следующую конфигурацию и вставьте ее в SampleConsoleApp.csproj (внутриProject
элемента).<PropertyGroup> <RestoreSources> https://api.nuget.org/v3/index.json; ../SimpleMathProjection/nuget </RestoreSources> </PropertyGroup> <ItemGroup> <PackageReference Include="SimpleMathComponent" Version="0.1.0-prerelease" /> </ItemGroup>
Это важно
Заданный путь для пакета
RestoreSources
, показанного выше, имеет значение../SimpleMathProjection/nuget
. Этот путь корректный, если вы следовали шагам, описанным в этом пошаговом руководстве, так что проекты SimpleMathComponent и SampleConsoleApp оба находятся в одной папке (NetProjectionSample
папке в данном случае). Если вы сделали что-то другое, вам потребуется соответствующим образом настроить этот путь. Кроме того, вы можете добавить локальный источник пакетов NuGet в вашу проект.Измените файл Program.cs , чтобы использовать функциональные возможности, предоставляемые SimpleMathComponent.
var x = new SimpleMathComponent.SimpleMath(); Console.WriteLine("Adding 5.5 + 6.5 ..."); Console.WriteLine(x.add(5.5, 6.5).ToString());
Сохраните и закройте файлы, которые вы только что редактировали, и создайте и запустите консольное приложение. Вы увидите приведенные ниже выходные данные.
Известные проблемы
- При создании проекта проекции может возникнуть ошибка: ошибка MSB3271 Произошла несоответствие между архитектурой процессора создаваемого проекта MSIL и архитектурой процессора x86 файла реализации ..\SimpleMathComponent.dll" для ".. \SimpleMathComponent.winmd". Это несоответствие может привести к сбоям среды выполнения. Рекомендуется изменить целевую архитектуру процессора проекта с помощью Configuration Manager, чтобы выровнять архитектуры процессора между файлом проекта и реализацией, или выбрать winmd-файл с файлом реализации с архитектурой процессора, которая соответствует целевой архитектуре процессора проекта. Чтобы обойти эту ошибку, добавьте следующее свойство в файл проекта библиотеки C#:
<PropertyGroup> <!-- Workaround for MSB3271 error on processor architecture mismatch --> <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch> </PropertyGroup>
Дополнительные рекомендации
Сборка проекции C# (или интероперабельности), которую мы показали, как создать в этом разделе, довольно простая — у нее нет зависимостей от других компонентов. Но чтобы создать проекцию C# для компонента C++/WinRT с ссылками на типы Windows App SDK, в проекте проекции необходимо добавить ссылку на пакет NuGet Windows App SDK. Если отсутствуют такие ссылки, вы увидите такие ошибки, как "Тип <T> не удалось найти".
Еще одна вещь, которую мы делаем в этом разделе, заключается в распространении проекции в виде пакета NuGet. Этот в настоящее время необходим.
Ресурсы
Windows developer