Générez une projection C# à partir d'un composant C++/WinRT, distribuez-la en tant que NuGet pour les applications .NET
Dans cette rubrique, nous passons en revue l'utilisation de C#/WinRT pour générer un assembly de projection (ou d'interopérabilité) C# .NET à partir d'un composant Windows Runtime C++/WinRT et le distribuons en tant que package NuGet pour les applications .NET.
Dans .NET 6 et versions ultérieures, la consommation des fichiers de métadonnées Windows (WinMD) n'est plus prise en charge (voir La prise en charge intégrée de WinRT est supprimée de .NET). Au lieu de cela, l'outil C#/WinRT peut être utilisé pour générer un assembly de projection pour n'importe quel fichier WinMD, ce qui permet ensuite la consommation de composants WinRT à partir d'applications .NET. Un assembly de projection est également connu sous le terme d’assembly d’interopérabilité. Cette procédure pas à pas va vous montrer comment effectuer les tâches suivantes :
- Utiliser le package C#/WinRT pour générer une projection C# à partir d’un composant C++/WinRT.
- Distribuer le composant, avec l’assembly de projection, sous la forme d’un package NuGet.
- Consommer le package NuGet à partir d’une application console .NET.
Prerequisites
Pour effectuer cette procédure pas à pas et l’exemple associé, vous avez besoin des outils et composants suivants :
- Visual Studio 2022 (ou Visual Studio 2019) avec la charge de travail Développement pour la plateforme Windows universelle installée. Dans Détails de l’installation>Développement pour la plateforme Windows universelle, cochez l’option Outils de plateforme Windows universelle C++ (v14x).
- SDK .NET 6.0 ou version ultérieure.
Visual Studio 2019 uniquement. L’extension VSIX C++/WinRT, qui fournit des modèles de projet C++/WinRT dans Visual Studio. Les modèles de projet sont intégrés à Visual Studio 2022.
Dans cette procédure pas à pas, nous utiliserons Visual Studio 2022 et .NET 6.
Important
En outre, vous devez télécharger ou cloner l’exemple de code pour cette rubrique à partir de l’exemple de projection C#/WinRT sur GitHub. Accédez à CsWinRT, puis cliquez sur le bouton Code vert pour accéder à l’URL git clone
. Veillez à lire le fichier README.md de l’exemple.
Créer un composant Windows Runtime C++/WinRT simple
Pour effectuer cette procédure pas à pas, vous devez déjà avoir installé un composant Windows Runtime (WRC) C++/WinRT à partir duquel sera généré l’assembly de projection C#.
Cette procédure pas à pas utilise le WRC SimpleMathComponent de l’exemple de projection C#/WinRT sur GitHub, que vous avez déjà téléchargé ou cloné. SimpleMathComponent a été créé à partir du modèle de projet Composant Windows Runtime (C++/WinRT) de Visual Studio (qui est fourni avec Visual Studio 2022 ou avec l’extension VSIX C++/WinRT).
Pour ouvrir le projet SimpleMathComponent dans Visual Studio, ouvrez le fichier \CsWinRT\src\Samples\NetProjectionSample\CppWinRTComponentProjectionSample.sln
, qui se trouve dans votre téléchargement ou clone du dépôt.
Le code de ce projet fournit les fonctionnalités nécessaires pour les opérations mathématiques de base indiquées dans le fichier d’en-tête ci-dessous.
// 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);
};
}
Vous pouvez vérifier que la propriété Compatible avec Windows Desktop est définie sur Oui pour le projet SimpleMathComponent du composant Windows Runtime C++/WinRT. Pour cela, dans les propriétés du projet SimpleMathComponent, sous Propriétés de configuration>Général>Valeurs par défaut du projet, définissez la propriété Compatible avec Windows Desktop sur Oui. Cela permet de vous assurer que les fichiers binaires du runtime appropriés sont chargés en vue de la consommation d’applications de bureau .NET.
Pour connaître les étapes détaillées de la création d’un composant C++/WinRT et de la génération d’un fichier WinMD, consultez Composants Windows Runtime avec C++/WinRT.
Note
Si vous implémentez IInspectable::GetRuntimeClassName dans votre composant, il doit retourner un nom de classe WinRT valide. Comme C#/WinRT utilise la chaîne de nom de classe pour l’interopérabilité, un nom de classe runtime incorrect lève une exception InvalidCastException.
Ajouter un projet de projection à la solution de composant
Tout d’abord, en gardant la solution CppWinRTComponentProjectionSample ouverte dans Visual Studio, supprimez le projet SimpleMathProjection de cette solution. Ensuite, supprimez de votre système de fichiers le dossier SimpleMathProjection (ou renommez-le si vous préférez). Ces étapes sont obligatoires pour poursuivre cette procédure pas à pas.
Ajoutez un nouveau projet de bibliothèque C# à votre solution.
- Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le nœud de votre solution, puis cliquez sur Ajouter>Nouveau projet.
- Dans la boîte de dialogue Ajouter un nouveau projet, tapez Bibliothèque de classes dans la zone de recherche. Choisissez C# dans la liste des langages, puis choisissez Windows dans la liste des plateformes. Choisissez le modèle de projet C# appelé simplement Bibliothèque de classes (sans préfixe ni suffixe), puis cliquez sur Suivant.
- Nommez le nouveau projet SimpleMathProjection. L’emplacement est en principe déjà défini sur le même dossier
\CsWinRT\src\Samples\NetProjectionSample
que celui dans lequel se trouve le dossier SimpleMathComponent, mais vérifiez quand même ce point. Cliquez ensuite sur Suivant. - Dans la page Informations supplémentaires, sélectionnez .NET 6.0 (prise en charge à long terme), puis choisissez Créer.
Supprimez le fichier stub Class1.cs du projet.
Effectuez les étapes ci-dessous pour installer le package NuGet C#/WinRT.
- Dans l’Explorateur de solutions, cliquez avec le bouton droit sur votre projet SimpleMathProjection, puis sélectionnez Gérer les packages NuGet.
- Sous l’onglet Parcourir, tapez ou collez Microsoft.Windows.CsWinRT dans la zone de recherche ; dans les résultats de la recherche, sélectionnez l’élément affichant la dernière version, puis cliquez sur Installer pour installer le package dans le projet SimpleMathProjection.
Ajoutez à SimpleMathProjection une référence de projet au projet SimpleMathComponent. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le nœud Dépendances sous le nœud de projet SimpleMathProjection, sélectionnez Ajouter une référence de projet, puis sélectionnez le projet SimpleMathComponent >OK.
N’essayez pas de générer le projet pour le moment. Nous le ferons plus tard.
Votre Explorateur de solutions doit maintenant ressembler à ceci (vos numéros de version sont différents).
Générer des projets en dehors de la source
Pour la solution CppWinRTComponentProjectionSample fournie dans l’exemple de projection C#/WinRT (que vous avez téléchargé ou cloné à partir de GitHub, et qui est maintenant ouvert), l’emplacement de sortie de la build est configuré avec le fichier Directory.Build.props pour une génération en dehors de la source. Cela signifie que les fichiers de la sortie de la build sont générés en dehors du dossier source. Nous vous recommandons de choisir la génération en dehors de la source si vous utilisez l’outil C#/WinRT. Cela empêche le compilateur C# de sélectionner par inadvertance tous les fichiers *.cs sous le répertoire racine du projet, ce qui pourrait provoquer des erreurs de type en double (par exemple, au moment de la compilation pour plusieurs configurations et/ou plateformes).
Bien que cela soit déjà configuré pour la solution CppWinRTComponentProjectionSample, effectuez les étapes ci-dessous pour vous entraîner à faire votre propre configuration.
Pour configurer votre solution en vue d’une génération en dehors de la source :
Avec la solution CppWinRTComponentProjectionSample toujours ouverte, cliquez avec le bouton droit sur le nœud de la solution, puis sélectionnez Ajouter>Nouvel élément. Sélectionnez l’élément Fichier XML, puis nommez-le Directory.Build.props (sans extension
.xml
). Cliquez sur Oui pour remplacer le fichier existant.Remplacez le contenu de Directory.Build.props par la configuration ci-dessous.
<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>
Enregistrez et fermez le fichier Directory.Build.props.
Modifier le fichier projet pour exécuter C#/WinRT
Avant de pouvoir appeler l’outil cswinrt.exe
pour générer l’assembly de projection, vous devez d’abord modifier le fichier projet afin d’y définir certaines propriétés du projet.
Dans l’Explorateur de solutions, double-cliquez sur le nœud SimpleMathProjection pour ouvrir le fichier projet dans l’éditeur.
Mettez à jour l’élément
TargetFramework
pour qu’il cible une version spécifique du SDK Windows. Cette opération ajoute les dépendances d’assembly qui sont nécessaires à la prise en charge de l’interopérabilité et de la projection. Cet exemple cible la version net6.0-windows10.0.19041.0 du SDK Windows (également connue sous le nom de Windows 10, version 2004). Définissez l’élémentPlatform
sur AnyCPU afin que l’assembly de projection résultant puisse être référencé à partir de n’importe quelle architecture d’application. Pour permettre aux applications de référencement de prendre en charge les versions antérieures du SDK Windows, vous pouvez également définir la propriétéTargetPlatformMinimumVersion
.<PropertyGroup> <TargetFramework>net6.0-windows10.0.19041.0</TargetFramework> <!-- Set Platform to AnyCPU to allow consumption of the projection assembly from any architecture. --> <Platform>AnyCPU</Platform> </PropertyGroup>
Note
Pour cette procédure pas à pas et l’exemple de code associé, la solution est conçue pour x64 et Release. Notez que le projet SimpleMathProjection est configuré pour être créé pour AnyCPU pour toutes les configurations d'architecture de solution.
Ajoutez un deuxième élément
PropertyGroup
(immédiatement après le premier) qui définit plusieurs propriétés C#/WinRT.<PropertyGroup> <CsWinRTIncludes>SimpleMathComponent</CsWinRTIncludes> <CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir> </PropertyGroup>
Voici quelques détails sur les paramètres de cet exemple :
- La propriété
CsWinRTIncludes
spécifie les espaces de noms à projeter. - La propriété
CsWinRTGeneratedFilesDir
définit le répertoire de sortie dans lequel les fichiers sources de la projection sont générés. Cette propriété a la valeurOutDir
, qui a été définie dans Directory.Build.props dans la section ci-dessus.
- La propriété
Enregistrez et fermez le fichier SimpleMathProjection.csproj, puis cliquez sur pour Recharger les projets si nécessaire.
Créer un package NuGet avec la projection
Pour distribuer l’assembly de projection aux développeurs d’applications .NET, vous pouvez créer automatiquement un package NuGet en ajoutant des propriétés de projet supplémentaires au moment de la génération de la solution. Pour des cibles .NET, le package NuGet doit inclure l’assembly de projection et l’assembly d’implémentation du composant.
Effectuez les étapes ci-dessous pour ajouter un fichier de spécifications NuGet (
.nuspec
) au projet SimpleMathProjection.- Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le nœud SimpleMathProjection, choisissez Ajouter>Nouveau dossier, et nommez le dossier nuget.
- Cliquez avec le bouton droit sur le dossier nuget, choisissez Ajouter>Nouvel élément, choisissez Fichier XML, et nommez-le SimpleMathProjection.nuspec.
Dans l’Explorateur de solutions, double-cliquez sur le nœud SimpleMathProjection pour ouvrir le fichier projet dans l’éditeur. Ajoutez le groupe de propriétés suivant au fichier SimpleMathProjection.csproj qui est maintenant ouvert (ajoutez-le juste après les deux éléments
PropertyGroup
existants) pour générer le package automatiquement. Ces propriétés définissent le fichierNuspecFile
et le répertoire où générer le package NuGet.<PropertyGroup> <GeneratedNugetDir>.\nuget\</GeneratedNugetDir> <NuspecFile>$(GeneratedNugetDir)SimpleMathProjection.nuspec</NuspecFile> <OutputPath>$(GeneratedNugetDir)</OutputPath> <GeneratePackageOnBuild>true</GeneratePackageOnBuild> </PropertyGroup>
Note
Si vous préférez générer un package séparément, vous pouvez également choisir d’exécuter l’outil
nuget.exe
à partir de la ligne de commande. Pour plus d’informations sur la création d’un package NuGet, consultez Créer un package à l’aide de l’interface CLI nuget.exe.Ouvrez le fichier SimpleMathProjection.nuspec pour modifier les propriétés de création du package et collez le code suivant. L'extrait ci-dessous est un exemple de spécification NuGet pour distribuer SimpleMathComponent à plusieurs frameworks cibles. Notez que l'assembly de projection, SimpleMathProjection.dll, est spécifié à la place de SimpleMathComponent.winmd pour la cible
lib\net6.0-windows10.0.19041.0\SimpleMathProjection.dll
. Ce comportement est nouveau dans .NET 6 et versions ultérieures et est activé par C#/WinRT. L'assembly d'implémentation,SimpleMathComponent.dll
, doit également être distribué et sera chargé au moment de l'exécution.<?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>
Note
SimpleMathComponent.dll, l’assembly d’implémentation du composant, est propre à l’architecture. Si vous prenez en charge d'autres plates-formes (par exemple, x86 ou Arm64), vous devez d'abord créer SimpleMathComponent pour les plates-formes souhaitées et ajouter ces fichiers d'assemblage au dossier relatif au RID approprié. L’assembly de projection SimpleMathProjection.dll et le composant SimpleMathComponent.winmd sont tous les deux indépendants de l’architecture.
Enregistrez et fermez les fichiers que vous venez de modifier.
Générer la solution pour générer la projection et le package NuGet
Avant de générer la solution, vérifiez les paramètres du Gestionnaire de configuration dans Visual Studio, sous Build>Gestionnaire de configuration. Pour cette procédure pas à pas, définissez la Configuration sur Release et Platform sur x64 pour la solution.
Vous pouvez maintenant générer la solution. Cliquez avec le bouton droit sur le nœud de votre solution et sélectionnez Générer la solution. Cette opération génère successivement le projet SimpleMathComponent et le projet SimpleMathProjection. Le WinMD du composant et l’assembly d’implémentation (SimpleMathComponent.winmd et SimpleMathComponent.dll), les fichiers sources de la projection et l’assembly de projection (SimpleMathProjection.dll) sont également générés sous le répertoire de sortie _build. Vous pourrez également voir le package NuGet généré, SimpleMathComponent0.1.0-prerelease.nupkg, sous le dossier \SimpleMathProjection\nuget.
Important
Si l’un des fichiers mentionnés ci-dessus n’est pas généré, générez la solution une deuxième fois. Vous devrez peut-être également fermer et rouvrir la solution avant de la regénérer.
Vous devrez peut-être fermer et rouvrir la solution pour voir le package .nupkg
dans Visual Studio comme illustré (ou simplement sélectionner et désélectionner Afficher tous les fichiers).
Référencer le package NuGet dans une application console C# pour .NET 6
Pour consommer SimpleMathComponent à partir d’un projet .NET, il vous suffit d’ajouter dans un nouveau projet .NET une référence au package NuGet SimpleMathComponent0.1.0-prerelease.nupkg que nous avons créé dans la section précédente. Les étapes suivantes montrent comment procéder en créant une application console simple dans une solution distincte.
Effectuez les étapes suivantes pour créer une solution contenant un projet C# Application console (en créant ce projet dans une nouvelle solution, cela vous donne la possibilité de restaurer le package NuGet SimpleMathComponent de façon indépendante).
Important
Nous créons ce projet Application console dans le dossier
\CsWinRT\src\Samples\NetProjectionSample
, qui se trouve dans votre téléchargement ou clone de l’exemple de projection C#/WinRT.- Dans une nouvelle instance de Visual Studio, sélectionnez Fichier>Nouveau>Projet.
- Dans la boîte de dialogue Créer un projet, recherchez le modèle de projet Application console. Choisissez le modèle de projet C# appelé simplement Application console (sans préfixe ni suffixe), puis cliquez sur Suivant. Si vous utilisez Visual Studio 2019, le modèle de projet est Application console.
- Nommez le nouveau projet SampleConsoleApp, définissez son emplacement sur le même dossier
\CsWinRT\src\Samples\NetProjectionSample
que celui dans lequel se trouvent SimpleMathComponent et SimpleMathProjection, et cliquez sur Suivant. - Dans la page Informations supplémentaires, sélectionnez .NET 6.0 (prise en charge à long terme), puis choisissez Créer.
Dans l’Explorateur de solutions, double-cliquez sur le nœud SampleConsoleApp pour ouvrir le fichier projet SampleConsoleApp.csproj, puis modifiez les propriétés
TargetFramework
etPlatform
selon l’exemple suivant. Ajoutez l’élémentPlatform
s’il n’y est pas déjà.<PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net6.0-windows10.0.19041.0</TargetFramework> <Platform>x64</Platform> </PropertyGroup>
En gardant le fichier projet SampleConsoleApp.csproj ouvert, nous allons ensuite ajouter au projet SampleConsoleApp une référence au package NuGet SimpleMathComponent. Pour restaurer le package NuGet SimpleMathComponent au moment de la génération du projet, vous pouvez utiliser la propriété
RestoreSources
en spécifiant le chemin du dossier nuget dans votre solution de composant. Copiez la configuration ci-dessous et collez-la dans le fichier SampleConsoleApp.csproj (dans l’élémentProject
).<PropertyGroup> <RestoreSources> https://api.nuget.org/v3/index.json; ../SimpleMathProjection/nuget </RestoreSources> </PropertyGroup> <ItemGroup> <PackageReference Include="SimpleMathComponent" Version="0.1.0-prerelease" /> </ItemGroup>
Important
Le chemin
RestoreSources
du package SimpleMathComponent indiqué ci-dessus est défini sur../SimpleMathProjection/nuget
. Le chemin est correct si vous avez suivi les étapes de cette procédure pas à pas, où les projets SimpleMathComponent et SampleConsoleApp se trouvent dans le même dossier (dossierNetProjectionSample
ici). Si vous avez procédé différemment, changez ce chemin en conséquence. Vous pouvez aussi ajouter un flux de package NuGet local à votre solution.Modifiez le fichier Program.cs afin d’utiliser la fonctionnalité fournie par SimpleMathComponent.
var x = new SimpleMathComponent.SimpleMath(); Console.WriteLine("Adding 5.5 + 6.5 ..."); Console.WriteLine(x.add(5.5, 6.5).ToString());
Enregistrez et fermez les fichiers que vous venez de modifier, puis générez et exécutez l’application console. Vous voyez normalement la sortie ci-dessous.
Problèmes connus
- Lors de la construction du projet de projection, vous pouvez voir une erreur telle que : Erreur MSB3271 Il y avait une incompatibilité entre l'architecture du processeur du projet en cours de construction "MSIL" et l'architecture du processeur "x86" du fichier d'implémentation "..\SimpleMathComponent. dll" pour "..\SimpleMathComponent.winmd". Cette incompatibilité peut entraîner des échecs d'exécution. Veuillez envisager de modifier l'architecture de processeur ciblée de votre projet via le Microsoft Endpoint Configuration Manager afin d'aligner les architectures de processeur entre votre projet et le fichier d'implémentation, ou choisissez un fichier winmd avec un fichier d'implémentation dont l'architecture de processeur correspond à l'architecture de processeur ciblée de votre projet. Pour contourner cette erreur, ajoutez la propriété suivante au fichier projet de votre bibliothèque C# :
<PropertyGroup> <!-- Workaround for MSB3271 error on processor architecture mismatch --> <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch> </PropertyGroup>
Autres considérations
L’assembly de projection (ou d’interopérabilité) C# que nous avons montré comment créer dans cette rubrique est assez simple—il n’a pas de dépendances sur d’autres composants. Mais pour générer une projection C# pour un composant C++/WinRT qui contient des références aux types du SDK d’application Windows, dans le projet de projection, vous devez ajouter une référence au package NuGet du SDK d’application Windows. Si de telles références sont manquantes, vous verrez des erreurs telles que « Le type <T> est introuvable ».
Une autre chose que nous faisons dans cette rubrique est de distribuer la projection sous forme de package NuGet. C'est actuellement nécessaire.
Ressources
Windows developer