Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
I det här avsnittet går vi igenom hur du använder C#/WinRT för att generera en C# .NET projektion (eller interop)-sammansättning från en C++/WinRT-Windows Runtime komponent och distribuera den som ett NuGet-paket för .NET program.
I .NET 6 och senare stöds inte längre förbrukning av winMD-filer (Windows metadata) (se Built-in-stöd för WinRT tas bort från .NET). I stället kan C#/WinRT-verktyget användas för att generera en projektionssammansättning för alla WinMD-filer, vilket sedan möjliggör förbrukning av WinRT-komponenter från .NET program. En projektionssammansättning kallas även för en interop-sammansättning. Den här genomgången visar hur du gör följande:
- Använd C#/WinRT-paketet för att generera en C#-projektion från en C++/WinRT-komponent.
- Distribuera komponenten, tillsammans med projektionssammansättningen, som ett NuGet-paket.
- Använd NuGet-paketet från ett .NET-konsolprogram.
Förutsättningar
Den här genomgången och motsvarande exempel kräver följande verktyg och komponenter:
- Visual Studio 2022 eller senare med arbetslasten utveckling för Universell Windows-plattform installerad. I Installationsinformation>Universell Windows-plattform utveckling kontrollerar du alternativet C++ (v14x) Universell Windows-plattform verktyg.
- .NET 8.0 SDK (LTS) eller senare.
Vi använder Visual Studio 2022 eller senare och .NET 8 i den här genomgången.
Viktigt!
Du måste också ladda ned eller klona exempelkoden för det här avsnittet från C#/WinRT-projektionsexemplet på GitHub. Besök CsWinRToch klicka på den gröna koden för att få URL:en för git clone. Läs filen README.md för exemplet.
Skapa en enkel C++/WinRT-Windows Runtime komponent
Om du vill följa den här genomgången måste du först ha en C++/WinRT-Windows Runtime komponent (WRC) för att generera C#-projektionssammansättningen.
Den här genomgången använder SimpleMathComponent WRC från C#/WinRT-projektionsexemplet på GitHub, som du redan har laddat ned eller klonat. SimpleMathComponent skapades från projektmallen Windows Runtime Component (C++/WinRT) Visual Studio.
Öppna projektet SimpleMathComponent i Visual Studio genom att öppna filen \CsWinRT\src\Samples\NetProjectionSample\CppWinRTComponentProjectionSample.sln som du hittar i nedladdningen eller klonen av lagringsplatsen.
Koden i det här projektet innehåller funktioner för de grundläggande matematiska åtgärder som visas i rubrikfilen nedan.
// 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);
};
}
Du kan bekräfta att egenskapen Windows Desktop Compatible är inställd på Yes för SimpleMathComponent C++/WinRT Windows Runtime-komponentprojektet. Det gör du genom att i egenskaperna project för SimpleMathComponent, under Konfigurationsegenskaper>Allmänt>Project Standardvärden, ange egenskapen Windows Desktop Compatible till Yes. Det säkerställer att rätt runtime-binärfiler läses in för att använda av .NET-skrivbordsappar.
Mer detaljerade steg om hur du skapar en C++/WinRT-komponent och genererar en WinMD-fil finns i Windows Runtime komponenter med C++/WinRT.
Anmärkning
Om du implementerar IInspectable::GetRuntimeClassName i komponenten måste den returnera ett giltigt WinRT-klassnamn. Eftersom C#/WinRT använder klassnamnsträngen för interop, kommer ett felaktigt körningsklassnamn att orsaka en InvalidCastException.
Lägga till ett projektionsprojekt i komponentlösningen
Med lösningen CppWinRTComponentProjectionSample som fortfarande är öppen i Visual Studio tar du bort projektet SimpleMathProjection från lösningen. Ta sedan bort mappen SimpleMathProjection från filsystemet (eller byt namn på den om du vill). Dessa steg är nödvändiga så att du kan följa den här genomgången steg för steg.
Lägg till ett nytt C#-biblioteksprojekt i din lösning.
- Högerklicka på lösningsnoden i Prieskumník riešení och klicka på Lägg till>Ny Project.
- I dialogrutan Lägg till ett nytt projekt skriver du klassbibliotek i sökrutan. Välj C# i språklistan och välj sedan Windows i plattformslistan. Välj C#-projektmallen som heter helt enkelt klassbiblioteket (utan prefix eller suffix) och klicka på Nästa.
- Ge det nya projektet namnet SimpleMathProjection. Platsen bör redan vara inställd på samma
\CsWinRT\src\Samples\NetProjectionSamplemapp som mappen SimpleMathComponent finns i. men bekräfta det. Klicka sedan på Nästa. - På sidan Additional information väljer du .NET 8.0 (långsiktigt stöd) och väljer sedan Create.
Ta bort stub-filen Class1.cs från projektet.
Använd stegen nedan för att installera C#/WinRT NuGet-paketet.
- I Prieskumník riešení högerklickar du på projektet SimpleMathProjection och väljer Hantera NuGet-paket.
- På fliken Browse skriver eller klistrar du in Microsoft.Windows. CsWinRT i sökrutan väljer du objektet med den senaste versionen i sökresultatet och klickar sedan på Install för att installera paketet i projektet SimpleMathProjection.
Lägg till i SimpleMathProjection en projektreferens till projektet SimpleMathComponent. I Prieskumník riešení högerklickar du på noden Dependencies under noden SimpleMathProjection project. välj Lägg till Project Referens och välj SimpleMathComponent project >OK.
Försök inte att skapa projektet än. Vi kommer att göra det i ett senare steg.
Hittills bör dina Prieskumník riešení se ut ungefär så här (versionsnumren skiljer sig åt).
Bygg projekt utanför källan
För lösningen CppWinRTComponentProjectionSample i C#/WinRT-projektionsexemplet (som du laddade ned eller klonade från GitHub, och nu har öppen) konfigureras byggutdataplatsen med filen Directory.Build.props för att skapa utanför källan. Det innebär att filer från kompileringsutdata genereras utanför källmappen. Vi rekommenderar att du skapar från källan när du använder C#/WinRT-verktyget. Det förhindrar att C#-kompilatorn oavsiktligt plockar upp alla *.cs filer under projektrotkatalogen, vilket kan orsaka duplicerade typfel (till exempel vid kompilering för flera konfigurationer och/eller plattformar).
Även om detta redan har konfigurerats för CppWinRTComponentProjectionSample lösning följer du stegen nedan för att få öva på att göra konfigurationen själv.
Så här konfigurerar du din lösning för att bygga ut från källan:
Med CppWinRTComponentProjectionSample lösning fortfarande öppen högerklickar du på lösningsnoden och väljer Lägg till>nytt objekt. Välj XML-fil objekt och ge det namnet Directory.Build.props (utan ett
.xmltillägg). Klicka på Ja för att skriva över den befintliga filen.Ersätt innehållet i Directory.Build.props med konfigurationen nedan.
<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>Spara och stäng filen Directory.Build.props.
Redigera projektfilen för att köra C#/WinRT
Innan du kan anropa verktyget cswinrt.exe för att generera projektionssammansättningen måste du först redigera projektfilen för att ange några projektegenskaper.
I Prieskumník riešení dubbelklickar du på noden SimpleMathProjection för att öppna projektfilen i redigeraren.
Uppdatera elementet
TargetFrameworkför att rikta in sig på en specifik Windows SDK-version. Detta lägger till sammansättningsberoenden som krävs för stöd för interop och projektion. Det här exemplet är avsett för Windows SDK-versionen net6.0-windows10.0.19041.0 (kallas även Windows 10 version 2004). AngePlatform-elementet till AnyCPU- så att den resulterande projektionssammansättningen kan refereras från valfri apparkitektur. Om du vill tillåta att refererande program stöder tidigare Windows SDK-versioner kan du också ange egenskapenTargetPlatformMinimumVersion.<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>Anmärkning
För den här genomgången och den relaterade exempelkoden skapas lösningen för x64 och Release. Observera att SimpleMathProjection-projektet är konfigurerat för att bygga för AnyCPU för alla lösningsarkitekturkonfigurationer.
Lägg till ett andra
PropertyGroupelement (omedelbart efter det första) som anger flera C#/WinRT-egenskaper.<PropertyGroup> <CsWinRTIncludes>SimpleMathComponent</CsWinRTIncludes> <CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir> </PropertyGroup>Här följer lite information om inställningarna i det här exemplet:
- Egenskapen
CsWinRTIncludesanger vilka namnområden som ska projiceras. - Egenskapen
CsWinRTGeneratedFilesDiranger utdatakatalogen där projektionskällfilerna genereras. Den här egenskapen är inställd påOutDir, som definieras i Directory.Build.props från avsnittet ovan.
- Egenskapen
Spara och stäng filen SimpleMathProjection.csproj och klicka för att Läs in projekt om det behövs.
Skapa ett NuGet-paket med projektionen
Om du vill distribuera projektionssammansättningen för .NET programutvecklare kan du automatiskt skapa ett NuGet-paket när du skapar lösningen genom att lägga till ytterligare projektegenskaper. För .NET mål måste NuGet-paketet innehålla projektionssammansättningen och implementeringssammansättningen från komponenten.
Följ stegen nedan om du vill lägga till en NuGet-specifikationsfil (
.nuspec) i SimpleMathProjection--projektet.- I Prieskumník riešení högerklickar du på noden SimpleMathProjection. välj Lägg till>Ny mapp och ge mappen namnet nuget.
- Högerklicka på mappen nuget, välj Lägg till>nytt objekt, välj XML-filoch ge den namnet SimpleMathProjection.nuspec.
I Prieskumník riešení dubbelklickar du på noden SimpleMathProjection för att öppna projektfilen i redigeraren. Lägg till följande egenskapsgrupp i den nu öppna SimpleMathProjection.csproj (omedelbart efter de två befintliga
PropertyGroupelementen) för att automatiskt generera paketet. Dessa egenskaper angerNuspecFileoch katalogen som ska generera NuGet-paketet.<PropertyGroup> <GeneratedNugetDir>.\nuget\</GeneratedNugetDir> <NuspecFile>$(GeneratedNugetDir)SimpleMathProjection.nuspec</NuspecFile> <OutputPath>$(GeneratedNugetDir)</OutputPath> <GeneratePackageOnBuild>true</GeneratePackageOnBuild> </PropertyGroup>Anmärkning
Om du föredrar att generera ett paket separat kan du också välja att köra verktyget
nuget.exefrån kommandoraden. Mer information om hur du skapar ett NuGet-paket finns i Skapa ett paket med hjälp av nuget.exe CLI-.Öppna filen SimpleMathProjection.nuspec för att redigera egenskaperna för att skapa paketet och klistra in följande kod. Kodfragmentet nedan är ett exempel på NuGet-specifikation för att distribuera SimpleMathComponent till flera målramverk. Observera att projekteringsmonteringen SimpleMathProjection.dllspecificeras istället för SimpleMathComponent.winmd för målet
lib\net6.0-windows10.0.19041.0\SimpleMathProjection.dll. Det här beteendet är nytt i .NET 6 och senare och aktiveras av C#/WinRT. Implementeringssammansättningen,SimpleMathComponent.dll, måste också distribueras och läses in vid körning.<?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>Anmärkning
SimpleMathComponent.dllär implementeringssammansättningen för komponenten arkitekturspecifik. Om du stöder andra plattformar (till exempel x86 eller Arm64) måste du först skapa SimpleMathComponent- för önskade plattformar och lägga till dessa sammansättningsfiler i lämplig RID-relativ mapp. Projektionssammansättningen SimpleMathProjection.dll och komponenten SimpleMathComponent.winmd är båda arkitekturneutrala.
Spara och stäng filerna som du nyss redigerade.
Skapa lösningen för att generera projektionen och NuGet-paketet
Innan du skapar lösningen kontrollerar du inställningarna Configuration Manager i Visual Studio under Build>Configuration Manager. I den här genomgången anger du Configuration till Release och Platform till x64- för lösningen.
Nu kan du skapa lösningen. Högerklicka på lösningsnoden och välj Build Solution. Detta skapar först projektet SimpleMathComponent och sedan projektet SimpleMathProjection. Komponenten WinMD och implementeringssammansättningen (SimpleMathComponent.winmd och SimpleMathComponent.dll), projektionskällans filer och projektionssammansättningen (SimpleMathProjection.dll), genereras alla under katalogen _build utdata. Du kan också se det genererade NuGet-paketet SimpleMathComponent0.1.0-prerelease.nupkgunder mappen \SimpleMathProjection\nuget.
Viktigt!
Om någon av filerna som nämns ovan inte genereras skapar du lösningen en andra gång. Du kan också behöva stänga och öppna lösningen igen innan du återskapar den.
Du kan behöva stänga och öppna lösningen igen för att .nupkg ska visas i Visual Studio som illustreras (eller bara välja och avmarkera Visa alla filer).
Referera till NuGet-paketet i ett C# .NET 6-konsolprogram
Om du vill använda SimpleMathComponent från ett .NET projekt, Du kan helt enkelt lägga till en referens till SimpleMathComponent0.1.0-prerelease.nupkg NuGet-paketet som vi skapade i föregående avsnitt i ett nytt .NET projekt. Följande steg visar hur du gör det genom att skapa en enkel konsolapp i en separat lösning.
Använd stegen nedan för att skapa en ny lösning som innehåller ett C# Console App-projekt (om du skapar projektet i en ny lösning kan du återställa SimpleMathComponent- NuGet-paketet separat).
Viktigt!
Vi kommer att skapa det nya Console App-projektet i mappen
\CsWinRT\src\Samples\NetProjectionSample, som du hittar i det nedladdade eller klonade exemplet på C#/WinRT-projektion.- I en ny instans av Visual Studio väljer du File>Ny>Project.
- I dialogrutan Skapa ett nytt projekt söker du efter projektmallen Console App. Välj C#-projektmallen som bara heter Console App (utan prefix eller suffix) och klicka på Nästa. Om du använder Visual Studio 2019 är projektmallen Konsolprogram.
- Ge det nya projektet namnet SampleConsoleApp, ange platsen till samma
\CsWinRT\src\Samples\NetProjectionSamplemapp som mapparna SimpleMathComponent och SimpleMathProjection ligger i, och klicka på Nästa. - På sidan Additional information väljer du .NET 8.0 (långsiktigt stöd) och väljer sedan Create.
I Prieskumník riešení, dubbelklicka på noden SampleConsoleApp för att öppna projektfilen SampleConsoleApp.csproj och redigera
TargetFrameworkochPlatformså att de ser ut som i följande lista. Lägg till elementetPlatformom det inte finns där.<PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net6.0-windows10.0.19041.0</TargetFramework> <Platform>x64</Platform> </PropertyGroup>Med SampleConsoleApp.csproj projektfilen fortfarande öppen, lägger vi nästa till i SampleConsoleApp projektet en referens till SimpleMathComponent NuGet-paketet. Om du vill återställa SimpleMathComponent NuGet när du skapar projektet kan du använda egenskapen
RestoreSourcesmed sökvägen till mappen nuget i komponentlösningen. Kopiera följande konfiguration och klistra in den i SampleConsoleApp.csproj (inuti elementetProject).<PropertyGroup> <RestoreSources> https://api.nuget.org/v3/index.json; ../SimpleMathProjection/nuget </RestoreSources> </PropertyGroup> <ItemGroup> <PackageReference Include="SimpleMathComponent" Version="0.1.0-prerelease" /> </ItemGroup>Viktigt!
Den
RestoreSourcessökvägen för paketet SimpleMathComponent som visas ovan är inställd på../SimpleMathProjection/nuget. Den sökvägen är korrekt förutsatt att du har följt stegen i den här genomgången, så att SimpleMathComponent- och SampleConsoleApp projekt båda finns i samma mapp (mappenNetProjectionSamplei det här fallet). Om du har gjort något annorlunda, måste du justera sökvägen därefter. Du kan också lägga till ett lokalt NuGet-paketflöde till din lösning.Redigera Program.cs-filen för att använda funktionerna som tillhandahålls av SimpleMathComponent.
var x = new SimpleMathComponent.SimpleMath(); Console.WriteLine("Adding 5.5 + 6.5 ..."); Console.WriteLine(x.add(5.5, 6.5).ToString());Spara och stäng de filer som du precis redigerade och skapa och kör konsolappen. Du ska kunna se resultatet nedan.
Kända problemområden
- När du skapar ett projektionsprojekt kan du få ett felmeddelande som lyder: Error MSB3271 Det uppstod en skillnad mellan processorarkitekturerna för projektet som skapades "MSIL" och processorarkitekturen "x86", för implementeringsfilen "..\SimpleMathComponent.dll" för "..\SimpleMathComponent.winmd". Denna skillnad kan orsaka körningsfel. Överväg att ändra projektets målarkitektur för processorn via Configuration Manager för att justera processorarkitekturerna mellan projektet och implementeringsfilen, eller välj en winmd-fil med en implementeringsfil som har en processorarkitektur som matchar projektets målarkitektur. För att kringgå det här felet, lägg till följande egenskap i C#-biblioteksprojektfilen:
<PropertyGroup> <!-- Workaround for MSB3271 error on processor architecture mismatch --> <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch> </PropertyGroup>
Ytterligare överväganden
Den C#-projektion (eller interop)-sammansättning som vi visade hur du skapar i det här avsnittet är ganska enkel – den har inte beroenden för andra komponenter. Men för att generera en C#-projektion för en C++/WinRT-komponent som har referenser till Windows App SDK typer måste du i projektionsprojekt lägga till en referens till Windows App SDK NuGet-paketet. Om sådana referenser saknas visas fel som "Type <T> could not found" (Typ <T> kunde inte hittas).
En annan sak som vi gör i det här avsnittet är att distribuera projektionen som ett NuGet-paket. Den är för närvarande nödvändig.
Resurser
Windows developer