Sdílet prostřednictvím


Generování projekce jazyka C# z komponenty C++/WinRT, distribuce jako NuGet pro aplikace .NET

V tomto tématu si projdeme použití C#/WinRT k vygenerování projekce (nebo zprostředkovatelského) sestavení C# .NET z komponenty C++/WinRT Windows Runtime a jeho distribuování jako balíčku NuGet pro aplikace .NET.

V .NET 6 a novějších už není podporována spotřeba souborů metadat Windows (WinMD) (viz integrovaná podpora WinRT se odebere z rozhraní .NET). Místo toho lze nástroj C#/WinRT použít k vygenerování sestavení projekce pro libovolný soubor WinMD, který pak umožňuje spotřebu komponent WinRT z aplikací .NET. Sestavení projekce je také známé jako interoperabilní sestavení. V tomto názorném postupu se dozvíte, jak postupovat následovně:

  • Pomocí balíčku C#/WinRT vygenerujte projekce jazyka C# z komponenty C++/WinRT.
  • Distribuujte komponentu spolu se sestavením projekce jako balíček NuGet.
  • Použijte balíček NuGet z konzolové aplikace .NET

Požadavky

Tento názorný postup a odpovídající ukázka vyžadují následující nástroje a komponenty:

  • Visual Studio 2022 (nebo Visual Studio 2019) s nainstalovanou sadou nástrojů pro vývoj pro Univerzální platformu Windows. V části Podrobnosti o instalaci>, týkající se vývoje univerzální platformy Windows, zkontrolujte možnost C++ (v14x) nástroje pro univerzální platformu Windows.
  • .NET 6.0 SDK nebo novější

pouze sady Visual Studio 2019. Rozšíření C++/WinRT VSIX, které poskytuje šablony projektů C++/WinRT ve Visual Studiu. Šablony projektů jsou integrované v sadě Visual Studio 2022.

V tomto názorném postupu budeme používat Visual Studio 2022 a .NET 6.

Důležité

Také budete muset stáhnout nebo naklonovat vzorový kód pro toto téma z projekční ukázky C#/WinRT na GitHubu. Přejděte na CsWinRT a kliknutím na zelené tlačítko Kód získejte git clone adresu URL. Nezapomeňte si pro ukázku přečíst soubor README.md .

Vytvoření jednoduché komponenty C++/WinRT Windows Runtime

Pokud chcete postupovat podle tohoto návodu, musíte mít nejprve součást C++/WinRT Windows Runtime (WRC), ze které chcete vygenerovat sestavení projekce jazyka C#.

Tento návod využívá SimpleMathComponent WRC z ukázky projekce C#/WinRT na GitHubu, kterou jste již stáhli nebo naklonovali. SimpleMathComponent byl vytvořen ze šablony projektu Windows Runtime Component (C++/WinRT) v sadě Visual Studio, která je součástí sady Visual Studio 2022 nebo je dostupná s rozšířením C++/WinRT VSIX.

Pokud chcete otevřít projekt SimpleMathComponent v Visual Studio, otevřete soubor \CsWinRT\src\Samples\NetProjectionSample\CppWinRTComponentProjectionSample.sln, který najdete ve svém stažení nebo klonu úložiště.

Kód v tomto projektu poskytuje funkce základních matematických operací zobrazených v níže uvedeném souboru hlaviček.

// 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);
    };
}

Můžete potvrdit, že vlastnost Windows Desktop Compatible je nastavena na hodnotu Ano pro projekt SimpleMathComponent komponenty C++/WinRT Windows Runtime. Chcete-li to provést, ve vlastnostech projektu pro SimpleMathComponent, v části Vlastnosti konfigurace>Obecné>Project Defaultsnastavte vlastnost Windows Desktop Compatible na Ano. Tím se zajistí načtení správných binárních souborů modulu runtime pro využívání desktopových aplikací .NET.

stránka vlastností kompatibilní s plochou

Podrobnější postup vytvoření komponenty C++/WinRT a generování souboru WinMD najdete v tématu Součásti prostředí Windows Runtime s C++/WinRT.

Poznámka:

Pokud implementujete IInspectable::GetRuntimeClassName ve své komponentě, musí vrátit platný název třídy WinRT. Vzhledem k tomu, že jazyk C#/WinRT používá řetězec názvu třídy pro interoperabilitu, nesprávný název runtime třídy vyvolá výjimku InvalidCastException.

Přidání projektu projekce do řešení komponent

Nejprve v sadě Visual Studio otevřete řešení CppWinRTComponentProjectionSample a odeberte z řešení projekt SimpleMathProjection. Potom odstraňte ze systému souborů složku SimpleMathProjection (nebo ji přejmenujte, pokud chcete). Tyto kroky jsou nezbytné, abyste mohli postupovat podle tohoto podrobného návodu.

  1. Přidejte do svého řešení nový projekt knihovny C#.

    1. V Průzkumník řešeníklikněte pravým tlačítkem na uzel řešení a klikněte na Přidat>Nový projekt.
    2. V dialogovém okně Přidat nový projekt zadejte do vyhledávacího pole Knihovna tříd. V seznamu jazyků zvolte jazyk C# a pak ze seznamu platforem zvolte Windows . Zvolte šablonu projektu jazyka C#, která se nazývá jednoduše knihovna tříd (bez předpon ani přípon) a klikněte na tlačítko Další.
    3. Pojmenujte nový projekt SimpleMathProjection. Umístění by již mělo být nastaveno na stejnou \CsWinRT\src\Samples\NetProjectionSample složku, ve které je složka SimpleMathComponent , ale potvrďte to. Pak klikněte na tlačítko Další.
    4. Na stránce Další informace vyberte .NET 6.0 (dlouhodobá podpora), a pak vyberte Vytvořit.
  2. Odstraňte zástupný Class1.cs soubor z projektu.

  3. Pomocí následujícího postupu nainstalujte balíček NuGet C#/WinRT.

    1. V Průzkumníku řešeníklikněte pravým tlačítkem na projekt SimpleMathProjection a vyberte Spravovat balíčky NuGet.
    2. Na kartě Procházet zadejte nebo vložte Microsoft.Windows.CsWinRT do vyhledávacího pole, ve výsledcích hledání vyberte položku s nejnovější verzí a poté klepněte na tlačítko Nainstalovat a nainstalujte balíček do projektu SimpleMathProjection .
  4. Přidejte do SimpleMathProjection odkaz na projekt SimpleMathComponent . V Průzkumníku řešeníklikněte pravým tlačítkem na uzel Závislosti pod uzlem projektu SimpleMathProjection, vyberte Přidání reference projektua vyberte projekt SimpleMathComponent>OK.

Zatím se nepokoušejte sestavit projekt. Uděláme to v pozdějším kroku.

Zatím by průzkumníka řešení měl vypadat nějak takto (vaše čísla verzí se budou lišit).

Průzkumník řešení zobrazující závislosti projektu projekce

Vytváření projektů mimo zdroj

Pro řešení CppWinRTComponentProjectionSample v ukázce C#/WinRT projekce (kterou jste stáhli nebo naklonovali z GitHubu a teď máte otevřené), je výstupní umístění sestavení nakonfigurované s Directory.Build.props pro sestavení ze zdrojového. To znamená, že soubory z výstupu sestavení se generují mimo zdrojové složky. Pokud používáte nástroj C#/WinRT, doporučujeme vytvořit ho ze zdroje. To brání kompilátoru jazyka C# neúmyslně vyzvednout všechny soubory *.cs v kořenovém adresáři projektu, což může způsobit chyby duplicitního typu (například při kompilaci pro více konfigurací a/nebo platforem).

I když je to už nakonfigurované pro řešení CppWinRTComponentProjectionSample , postupujte podle následujících kroků a vyzkoušejte si konfiguraci sami.

Nakonfigurujte své řešení pro sestavení mimo zdroj:

  1. Když je řešení CppWinRTComponentProjectionSample stále otevřené, klikněte pravým tlačítkem myši na uzel řešení a vyberte Přidat>Novou položku. Vyberte položku soubor XML a pojmenujte ji Directory.Build.props (bez přípony .xml ). Chcete-li přepsat existující soubor, klikněte na tlačítko Ano .

  2. Obsah adresáře.Build.props nahraďte konfigurací níže.

    <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>
    
  3. Uložte a zavřete soubor Directory.Build.props .

Úprava souboru projektu pro spuštění C#/WinRT

Než budete moci vyvolat cswinrt.exe nástroj pro generování sestavení projekce, musíte nejprve upravit soubor projektu a zadat několik vlastností projektu.

  1. V Průzkumníku řešenídvakrát klikněte na uzel SimpleMathProjection a otevřete soubor projektu v editoru.

  2. TargetFramework Aktualizujte element tak, aby cílil na konkrétní verzi sady Windows SDK. Tím se přidají závislosti sestavení, které jsou nezbytné pro podporu interoperability a projekce. Tato ukázka cílí na sadu Windows SDK verze net6.0-windows10.0.19041.0 (označovaná také jako Windows 10 verze 2004). Nastavte prvek Platform na AnyCPU tak, aby výsledné sestavení projekce bylo možné použít v architektuře jakékoli aplikace. Pokud chcete povolit odkazování aplikací na podporu starších verzí sady Windows SDK, můžete také nastavit TargetPlatformMinimumVersion vlastnost.

    <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>
    

    Poznámka:

    Pro účely tohoto názorného postupu a souvisejícího ukázkového kódu je řešení sestavené pro platformu x64 a release. Všimněte si, že projekt SimpleMathProjection je nakonfigurovaný tak, aby se sestavoval pro AnyCPU pro všechny konfigurace architektury řešení.

  3. Přidejte druhý PropertyGroup prvek (bezprostředně za první), který nastaví několik vlastností C#/WinRT.

    <PropertyGroup>
      <CsWinRTIncludes>SimpleMathComponent</CsWinRTIncludes>
      <CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir>
    </PropertyGroup>
    

    Tady je několik podrobností o nastaveních v tomto příkladu:

    • Vlastnost CsWinRTIncludes určuje, které obory názvů se mají projektovat.
    • Vlastnost CsWinRTGeneratedFilesDir nastaví výstupní adresář, ve kterém jsou generovány zdrojové soubory projekce. Tato vlastnost je nastavena na OutDir, definován v Directory.Build.props z výše uvedené části.
  4. Uložte a zavřete soubor SimpleMathProjection.csproj a klikněte na Znovu načíst projekty v případě potřeby.

Vytvoření balíčku NuGet s projekcí

Pokud chcete distribuovat sestavení projekce pro vývojáře aplikací .NET, můžete při sestavování řešení automaticky vytvořit balíček NuGet přidáním dalších vlastností projektu. Pro cíle .NET musí balíček NuGet obsahovat sestavení projekce a sestavení implementace ze komponenty.

  1. Pomocí následujícího postupu přidejte do projektu .nuspec soubor specifikace NuGet ().

    1. V Průzkumníku řešení klikněte pravým tlačítkem na uzel SimpleMathProjection, zvolte Přidat>Nová složkaa pojmenujte složku nuget.
    2. Klikněte pravým tlačítkem myši na složku NuGet , zvolte Přidat>novou položku, zvolte soubor XML a pojmenujte ji SimpleMathProjection.nuspec.
  2. V Průzkumníku řešenídvakrát klikněte na uzel SimpleMathProjection a otevřete soubor projektu v editoru. Přidejte následující skupinu vlastností do nyní otevřené simpleMathProjection.csproj (hned za dva existující PropertyGroup prvky), aby se balíček automaticky vygeneroval. Tyto vlastnosti určují NuspecFile a adresář, ve kterém se má vygenerovat balíček NuGet.

    <PropertyGroup>
      <GeneratedNugetDir>.\nuget\</GeneratedNugetDir>
      <NuspecFile>$(GeneratedNugetDir)SimpleMathProjection.nuspec</NuspecFile>
      <OutputPath>$(GeneratedNugetDir)</OutputPath>
      <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
    </PropertyGroup>
    

    Poznámka:

    Pokud dáváte přednost samostatnému generování balíčku, můžete se také rozhodnout spustit nástroj nuget.exe z příkazového řádku. Další informace o vytvoření balíčku NuGet najdete v tématu Vytvoření balíčku pomocí rozhraní příkazového řádku nuget.exe.

  3. Otevřete soubor SimpleMathProjection.nuspec pro úpravu vlastností vytváření balíčku a vložte následující kód. Níže uvedený fragment kódu je příkladem specifikace NuGet pro distribuci SimpleMathComponent do více cílových architektur. Všimněte si, že sestavení projekce SimpleMathProjection.dllje specifikováno namísto SimpleMathComponent.winmd pro cíl lib\net6.0-windows10.0.19041.0\SimpleMathProjection.dll. Toto chování je v .NET 6 a novějších novinkách a je povoleno jazykem C#/WinRT. Sestavení implementace SimpleMathComponent.dllmusí být také distribuováno a bude načteno za běhu.

    <?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>
    

    Poznámka:

    SimpleMathComponent.dll, sestavení implementace pro komponentu, je specifické pro architekturu. Pokud podporujete jiné platformy (například x86 nebo Arm64), musíte nejprve sestavit SimpleMathComponent pro požadované platformy a přidat tyto soubory sestavení do příslušné složky relativního identifikátoru RID. Sestavení projekce SimpleMathProjection.dll a komponenta SimpleMathComponent.winmd jsou obě architektury neutrální.

  4. Uložte a zavřete soubory, které jste právě upravili.

Sestavení řešení pro vygenerování projekce a balíčku NuGet

Před sestavením řešení zkontrolujte nastavení nástroje Konfigurační Správce v sadě Visual Studio v části Sestavení>Konfigurační Správce. Pro účely tohoto návodu nastavte konfigurace na Release a Platform na x64 pro řešení.

V tuto chvíli můžete sestavit řešení. Klikněte pravým tlačítkem myši na uzel řešení a vyberte Sestavit řešení. Tím se nejprve sestaví projekt SimpleMathComponent a pak projekt SimpleMathProjection . Komponenta WinMD a implementační sestavení (SimpleMathComponent.winmd a SimpleMathComponent.dll), zdrojové soubory projekce a sestavení projekce (SimpleMathProjection.dll), budou všechny vygenerovány v adresáři výstupu _build. Ve složce \SimpleMathProjection\nuget také uvidíte vygenerovaný balíček NuGet SimpleMathComponent0.1.0-prerelease.nupkg.

Důležité

Pokud některý z výše uvedených souborů nebyl vygenerován, sestavte řešení ještě jednou. Před opětovným sestavením možná budete muset řešení zavřít a znovu otevřít.

Možná budete muset řešení zavřít a znovu otevřít, aby se .nupkg zobrazil ve Visual Studio, jak je uvedeno na obrázku (nebo stačí vybrat a zrušit výběr Show All Files).

Průzkumník řešení zobrazující generování projekce

Odkaz na balíček NuGet v konzolové aplikaci C# .NET 6

Pokud chcete použít SimpleMathComponent z projektu .NET, můžete jednoduše přidat do nového projektu .NET odkaz na simpleMathComponent0.1.0-prerelease.nupkg NuGet, který jsme vytvořili v předchozí části. Následující kroky ukazují, jak to provést vytvořením jednoduché konzolové aplikace v samostatném řešení.

  1. Pomocí následujícího postupu vytvořte nové řešení obsahující projekt konzolové aplikace jazyka C# (vytvoření tohoto projektu v novém řešení umožňuje nezávisle obnovit balíček NuGet SimpleMathComponent ).

    Důležité

    Tento nový projekt konzolové aplikace vytvoříme uvnitř \CsWinRT\src\Samples\NetProjectionSample složky, kterou najdete ve stažené nebo klonované ukázce projekce C#/WinRT.

    1. V nové instanci sady Visual Studio vyberte File>New>Project.
    2. V dialogovém okně Vytvořit nový projekt vyhledejte šablonu projektu konzolové aplikace . Zvolte šablonu projektu C#, která se nazývá jednoduše konzolová aplikace (bez předpon ani přípon), a klikněte na Další. Pokud používáte Visual Studio 2019, šablona projektu je Konzolová aplikace.
    3. Pojmenujte nový projekt SampleConsoleApp, nastavte jeho umístění na stejnou \CsWinRT\src\Samples\NetProjectionSample složku, ve které jsou složky SimpleMathComponent a SimpleMathProjection , a klepněte na tlačítko Další.
    4. Na stránce Další informace vyberte .NET 6.0 (dlouhodobá podpora), a pak vyberte Vytvořit.
  2. V Průzkumníku řešenípoklikejte na uzel SampleConsoleApp, otevřete soubor projektu SampleConsoleApp.csproj a upravte vlastnosti TargetFramework a Platform, aby vypadaly, jak je znázorněno v následujícím výpisu. Přidejte prvek Platform, pokud tam není.

    <PropertyGroup>
      <OutputType>Exe</OutputType>
      <TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
      <Platform>x64</Platform>
    </PropertyGroup>
    
  3. Se souborem projektu SampleConsoleApp.csproj stále otevřeným, přidáme do projektu SampleConsoleApp odkaz na NuGet balíček SimpleMathComponent. Pokud chcete obnovit SimpleMathComponent NuGet při sestavování projektu, můžete použít RestoreSources vlastnost s cestou ke složce nuget v řešení komponent. Zkopírujte následující konfiguraci a vložte ji do SampleConsoleApp.csproj (uvnitř elementu Project ).

    <PropertyGroup>
      <RestoreSources>
        https://api.nuget.org/v3/index.json;
        ../SimpleMathProjection/nuget
      </RestoreSources>
    </PropertyGroup>
    
    <ItemGroup>
      <PackageReference Include="SimpleMathComponent" Version="0.1.0-prerelease" />
    </ItemGroup>
    

    Důležité

    Cesta pro balíček SimpleMathComponent je nastavená na . Tato cesta je správná, pokud jste postupovali podle kroků v tomto návodu, aby projekty SimpleMathComponent a SampleConsoleApp byly ve stejné složce ( NetProjectionSample v tomto případě složka). Pokud jste udělali něco jiného, budete muset tuto cestu odpovídajícím způsobem upravit. Alternativně můžete do svého řešení přidat místní informační kanál balíčků NuGet.

  4. Upravte soubor Program.cs tak, aby používal funkce, které poskytuje SimpleMathComponent.

    var x = new SimpleMathComponent.SimpleMath();
    Console.WriteLine("Adding 5.5 + 6.5 ...");
    Console.WriteLine(x.add(5.5, 6.5).ToString());
    
  5. Uložte a zavřete soubory, které jste právě upravili, a sestavte a spusťte konzolovou aplikaci. Měl by se zobrazit následující výstup.

    výstup Console NET5

Známé problémy

  • Při sestavování projektu projekce se může zobrazit chyba, například: Chyba MSB3271 Došlo k neshodě mezi architekturou procesoru projektu, který se sestavuje "MSIL" a architekturou procesoru , "x86", implementačním souborem ..\SimpleMathComponent.dll" pro ".. \SimpleMathComponent.winmd". Tato neshoda může způsobit selhání modulu runtime. Zvažte změnu cílové architektury procesoru projektu prostřednictvím Configuration Manageru tak, aby byly v souladu s architekturami procesoru mezi vaším projektem a implementačním souborem, nebo zvolte soubor winmd s implementačním souborem, který má architekturu procesoru, která odpovídá cílové architektuře procesoru vašeho projektu. Chcete-li tuto chybu obejít, přidejte do souboru projektu knihovny C#následující vlastnost:
    <PropertyGroup>
        <!-- Workaround for MSB3271 error on processor architecture mismatch -->
        <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
    </PropertyGroup>
    

Další aspekty

Sestavení projekce jazyka C# (nebo interop), které jsme ukázali, jak v tomto tématu vytvořit, je poměrně jednoduché – nemá závislosti na jiných komponentách. Pokud ale chcete vygenerovat projekce jazyka C# pro komponentu C++/WinRT, která obsahuje odkazy na typy sady Windows App SDK, musíte v projektu projekce přidat odkaz na balíček NuGet sady Windows App SDK. Pokud nějaké takové odkazy chybí, zobrazí se chyby jako "Typ <T> nelze nalézt".

Další věcí, kterou v tomto tématu děláme, je distribuce projekce jako balíčku NuGet. Tento je v současné době nezbytný.

Prostředky