Udostępnij za pomocą


Tworzenie składnika środowiska uruchomieniowego systemu Windows w języku C# do użycia z poziomu aplikacji C++/WinRT

W tym temacie przedstawiono proces dodawania prostego składnika języka C# do projektu C++/WinRT.

Program Visual Studio ułatwia tworzenie i wdrażanie własnych niestandardowych typów środowiska uruchomieniowego systemu Windows w projekcie składnika środowiska uruchomieniowego systemu Windows (WRC) napisanym za pomocą języka C# lub Visual Basic, a następnie do odwołowania się do tej wersji WRC z projektu aplikacji języka C++ oraz do korzystania z tych typów niestandardowych z tej aplikacji.

Wewnętrznie typy środowiska uruchomieniowego systemu Windows mogą używać dowolnej funkcji platformy .NET, która jest dozwolona w aplikacji platformy UWP.

Członkowie twojego typu mogą z zewnątrz uwidaczniać tylko typy środowiska uruchomieniowego systemu Windows jako parametry i wartości zwracane. Podczas tworzenia rozwiązania program Visual Studio kompiluje projekt WRC platformy .NET, a następnie wykonuje krok kompilacji, który tworzy plik metadanych systemu Windows (winmd). Jest to składnik środowiska uruchomieniowego systemu Windows (WRC), który program Visual Studio zawiera w aplikacji.

Uwaga / Notatka

Platforma .NET automatycznie mapuje niektóre powszechnie używane typy platformy .NET, takie jak typy danych pierwotnych i typy kolekcji, do odpowiedników środowiska uruchomieniowego systemu Windows. Te typy platformy .NET mogą być używane w interfejsie publicznym składnika środowiska uruchomieniowego systemu Windows i będą wyświetlane użytkownikom składnika jako odpowiednie typy środowiska uruchomieniowego systemu Windows. Zobacz składniki środowiska uruchomieniowego Windows w językach C# i Visual Basic.

Wymagania wstępne

Tworzenie pustej aplikacji

W programie Visual Studio utwórz nowy projekt przy użyciu szablonu projektu Blank App (C++/WinRT). Upewnij się, że używasz szablonu (C++/WinRT), a nie szablonu (uniwersalnego systemu Windows).

Ustaw nazwę nowego projektu na CppToCSharpWinRT, aby struktura folderów odpowiadała przewodnikowi.

Dodawanie składnika środowiska uruchomieniowego systemu Windows w języku C# do rozwiązania

W programie Visual Studio utwórz projekt składników: w Eksploratorze rozwiązań otwórz menu skrótów dla rozwiązania CppToCSharpWinRT i wybierz Dodaj, a następnie wybierz Nowy projekt, aby dodać nowy projekt w języku C# do rozwiązania. W sekcji Zainstalowane szablony okna dialogowego Dodawanie nowego projektu wybierz pozycję Visual C#, a następnie pozycję Windows, a potem Universal. Wybierz szablon składnika środowiska uruchomieniowego systemu Windows (uniwersalny system Windows) i wprowadź SampleComponent jako nazwę projektu.

Uwaga / Notatka

W oknie dialogowym Nowy projekt platformy uniwersalnej systemu Windows wybierz Windows 10 Creators Update (10.0; Kompilacja 15063) jako minimalną wersję. Aby uzyskać więcej informacji, zobacz sekcję Minimalna Wersja Aplikacji poniżej.

Dodawanie metody GetMyString w języku C#

W projekcie SampleComponent zmień nazwę klasy z Class1 na Example. Następnie dodaj dwa proste elementy członkowskie do klasy: prywatne pole int i metodę instancji o nazwie GetMyString.

    public sealed class Example
    {
        int MyNumber;

        public string GetMyString()
        {
            return $"This is call #: {++MyNumber}";
        }
    }

Uwaga / Notatka

Domyślnie klasa jest oznaczona jako publicznie zapieczętowana. Wszystkie klasy środowiska uruchomieniowego systemu Windows udostępniane przez składnik muszą być zapieczętowane.

Uwaga / Notatka

Opcjonalnie: Aby włączyć IntelliSense dla nowo dodanych członków, w Eksploratorze rozwiązań otwórz menu kontekstowe dla projektu SampleComponent, a następnie wybierz pozycję Build.

Odwołanie do przykładu języka C#Component z projektu CppToCSharpWinRT

W Eksploratorze rozwiązań w projekcie C++/WinRT otwórz menu skrótów dla References, a następnie wybierz pozycję Dodaj odwołanie, aby otworzyć okno dialogowe Dodaj odwołanie. Wybierz Projects, a następnie wybierz Solution. Zaznacz pole wyboru dla projektu SampleComponent i wybierz opcję OK, aby dodać odwołanie.

Uwaga / Notatka

Opcjonalnie: Aby włączyć funkcję IntelliSense dla projektu C++/WinRT, w Eksploratorze rozwiązań otwórz menu skrótów dla projektu CppToCSharpWinRT, a następnie wybierz pozycję Build.

Edytuj plik MainPage.h

Otwórz MainPage.h w projekcie CppToCSharpWinRT, i następnie dodaj dwa elementy. Najpierw dodaj #include "winrt/SampleComponent.h" na końcu instrukcji #include, a następnie pole winrt::SampleComponent::Example do struktury MainPage.

// MainPage.h
...
#include "winrt/SampleComponent.h"

namespace winrt::CppToCSharpWinRT::implementation
{
    struct MainPage : MainPageT<MainPage>
    {
...
        winrt::SampleComponent::Example myExample;
...
    };
}

Uwaga / Notatka

W programie Visual Studio MainPage.h jest wyświetlana w obszarze MainPage.xaml.

Edytuj MainPage.cpp

W MainPage.cppzmień implementację Mainpage::ClickHandler, aby wywołać metodę języka C# GetMyString.

void MainPage::ClickHandler(IInspectable const&, RoutedEventArgs const&)
{
    //myButton().Content(box_value(L"Clicked"));

    hstring myString = myExample.GetMyString();

    myButton().Content(box_value(myString));
}

Uruchamianie projektu

Teraz możesz skompilować i uruchomić projekt. Za każdym razem, gdy klikniesz przycisk, liczba w przycisku zwiększy się.

Zrzut ekranu C++/WinRT Windows wywołującego komponent C#

Wskazówka

W programie Visual Studio utwórz projekt składników: W Eksploratorze rozwiązań otwórz menu skrótów dla projektu CppToCSharpWinRT i wybierz pozycję właściwości , a następnie wybierz pozycję Debugowanie w obszarze właściwości konfiguracji . Ustaw typ debugera na zarządzany i natywny, jeśli chcesz debugować kod C# (zarządzany) i C++ (natywny). właściwości debugowania języka C++

Minimalna wersja aplikacji

Minimalna aplikacja w wersji projektu C# będzie zarządzać wersją platformy .NET używaną do kompilowania aplikacji. Na przykład wybranie opcji Windows 10 Fall Creators Update (10.0; Kompilacja 16299) lub nowsza umożliwi obsługę procesorów .NET Standard 2.0 i Windows Arm64.

Wskazówka

Zalecamy używanie wersji Application Minimum niższych niż 16299, aby uniknąć dodatkowej konfiguracji kompilacji, jeśli obsługa platformy .NET Standard 2.0 lub Arm64 nie jest konieczna.

Skonfiguruj dla Windows 10 Fall Creators Update (10.0; Kompilacja 16299)

Wykonaj następujące kroki, aby włączyć obsługę platformy .NET Standard 2.0 lub Windows Arm64 w projektach języka C#, do których odwołuje się projekt C++/WinRT.

W programie Visual Studio przejdź do Eksploratora rozwiązań i otwórz menu skrótów dla projektu CppToCSharpWinRT. Wybierz Właściwości i ustaw minimalną wersję uniwersalnej aplikacji Windows na Windows 10 Fall Creators Update (10.0; Kompilacja 16299) (lub nowszą). Wykonaj to samo dla projektu SampleComponent.

W programie Visual Studio otwórz menu skrótów dla projektu CppToCSharpWinRT i wybierz Odładuj projekt, aby otworzyć CppToCSharpWinRT.vcxproj w edytorze tekstu.

Skopiuj i wklej następujący kod XML do pierwszego PropertyGroup w CPPWinRTCSharpV2.vcxproj.

   <!-- Start Custom .NET Native properties -->
   <DotNetNativeVersion>2.2.12-rel-31116-00</DotNetNativeVersion>
   <DotNetNativeSharedLibrary>2.2.8-rel-31116-00</DotNetNativeSharedLibrary>
   <UWPCoreRuntimeSdkVersion>2.2.14</UWPCoreRuntimeSdkVersion>
   <!--<NugetPath>$(USERPROFILE)\.nuget\packages</NugetPath>-->
   <NugetPath>$(ProgramFiles)\Microsoft SDKs\UWPNuGetPackages</NugetPath>
   <!-- End Custom .NET Native properties -->

Wartości DotNetNativeVersion, DotNetNativeSharedLibraryi UWPCoreRuntimeSdkVersion mogą się różnić w zależności od wersji programu Visual Studio. Aby ustawić je na poprawne wartości, otwórz %ProgramFiles(x86)%\Microsoft SDKs\UWPNuGetPackages i przyjrzyj się podkatalogowi dla każdej wartości w poniższej tabeli. Katalog %ProgramFiles(x86)%\Microsoft SDKs\UWPNuGetPackages\Microsoft.Net.Native.Compiler będzie miał podkatalog zawierający zainstalowaną wersję natywną platformy .NET, która rozpoczyna się od 2.2. W poniższym przykładzie jest to 2.2.12-rel-31116-00.

Zmienna MSBuild Katalog Przykład
DotNetNativeVersion %ProgramFiles(x86)%\Microsoft SDKs\UWPNuGetPackages\Microsoft.Net.Native.Compiler 2.2.12-rel-31116-00
DotNetNativeSharedLibrary %ProgramFiles(x86)%\Microsoft SDKs\UWPNuGetPackages\runtime.win10-x64.microsoft.net.native.sharedlibrary 2.2.8-rel-31116-00
UWPCoreRuntimeSdkVersion %ProgramFiles(x86)%\Microsoft SDKs\UWPNuGetPackages\Microsoft.Net.UWPCoreRuntimeSdk 2.2.14

Uwaga / Notatka

Istnieje wiele obsługiwanych architektur dla biblioteki Microsoft.Net.Native.SharedLibrary. Zastąp x64 odpowiednią architekturą. Na przykład architektura arm64 będzie znajdować się w katalogu %ProgramFiles(x86)%\Microsoft SDKs\UWPNuGetPackages\runtime.win10-arm64.microsoft.net.native.sharedlibrary.

Następnie, natychmiast po pierwszym PropertyGroup, dodaj następujące (bez zmian).

  <!-- Start Custom .NET Native targets -->
  <!-- Import all of the .NET Native / CoreCLR props at the beginning of the project -->
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\Microsoft.Net.UWPCoreRuntimeSdk\$(UWPCoreRuntimeSdkVersion)\build\Microsoft.Net.UWPCoreRuntimeSdk.props" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-x86.Microsoft.Net.UWPCoreRuntimeSdk\$(UWPCoreRuntimeSdkVersion)\build\runtime.win10-x86.Microsoft.Net.UWPCoreRuntimeSdk.props" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-x64.Microsoft.Net.UWPCoreRuntimeSdk\$(UWPCoreRuntimeSdkVersion)\build\runtime.win10-x64.Microsoft.Net.UWPCoreRuntimeSdk.props" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-arm.Microsoft.Net.UWPCoreRuntimeSdk\$(UWPCoreRuntimeSdkVersion)\build\runtime.win10-arm.Microsoft.Net.UWPCoreRuntimeSdk.props" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\Microsoft.Net.Native.Compiler\$(DotNetNativeVersion)\build\Microsoft.Net.Native.Compiler.props" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-x86.Microsoft.Net.Native.Compiler\$(DotNetNativeVersion)\build\runtime.win10-x86.Microsoft.Net.Native.Compiler.props" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-x64.Microsoft.Net.Native.Compiler\$(DotNetNativeVersion)\build\runtime.win10-x64.Microsoft.Net.Native.Compiler.props" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-arm.Microsoft.Net.Native.Compiler\$(DotNetNativeVersion)\build\runtime.win10-arm.Microsoft.Net.Native.Compiler.props" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-arm64.Microsoft.Net.Native.Compiler\$(DotNetNativeVersion)\build\runtime.win10-arm64.Microsoft.Net.Native.Compiler.props" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-x86.Microsoft.Net.Native.SharedLibrary\$(DotNetNativeSharedLibrary)\build\runtime.win10-x86.Microsoft.Net.Native.SharedLibrary.props" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-x64.Microsoft.Net.Native.SharedLibrary\$(DotNetNativeSharedLibrary)\build\runtime.win10-x64.Microsoft.Net.Native.SharedLibrary.props" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-arm.Microsoft.Net.Native.SharedLibrary\$(DotNetNativeSharedLibrary)\build\runtime.win10-arm.Microsoft.Net.Native.SharedLibrary.props" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-arm64.Microsoft.Net.Native.SharedLibrary\$(DotNetNativeSharedLibrary)\build\runtime.win10-arm64.Microsoft.Net.Native.SharedLibrary.props" />
  <!-- End Custom .NET Native targets -->

Na końcu pliku projektu, tuż przed tagiem zamykającym Project, dodaj następujący (niezmieniony).

  <!-- Import all of the .NET Native / CoreCLR targets at the end of the project -->
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-x86.Microsoft.Net.UWPCoreRuntimeSdk\$(UWPCoreRuntimeSdkVersion)\build\runtime.win10-x86.Microsoft.Net.UWPCoreRuntimeSdk.targets" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-x64.Microsoft.Net.UWPCoreRuntimeSdk\$(UWPCoreRuntimeSdkVersion)\build\runtime.win10-x64.Microsoft.Net.UWPCoreRuntimeSdk.targets" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-arm.Microsoft.Net.UWPCoreRuntimeSdk\$(UWPCoreRuntimeSdkVersion)\build\runtime.win10-arm.Microsoft.Net.UWPCoreRuntimeSdk.targets" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\Microsoft.Net.Native.Compiler\$(DotNetNativeVersion)\build\Microsoft.Net.Native.Compiler.targets" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-x86.Microsoft.Net.Native.Compiler\$(DotNetNativeVersion)\build\runtime.win10-x86.Microsoft.Net.Native.Compiler.targets" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-x64.Microsoft.Net.Native.Compiler\$(DotNetNativeVersion)\build\runtime.win10-x64.Microsoft.Net.Native.Compiler.targets" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-arm.Microsoft.Net.Native.Compiler\$(DotNetNativeVersion)\build\runtime.win10-arm.Microsoft.Net.Native.Compiler.targets" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-arm64.Microsoft.Net.Native.Compiler\$(DotNetNativeVersion)\build\runtime.win10-arm64.Microsoft.Net.Native.Compiler.targets" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-x86.Microsoft.Net.Native.SharedLibrary\$(DotNetNativeSharedLibrary)\build\runtime.win10-x86.Microsoft.Net.Native.SharedLibrary.targets" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-x64.Microsoft.Net.Native.SharedLibrary\$(DotNetNativeSharedLibrary)\build\runtime.win10-x64.Microsoft.Net.Native.SharedLibrary.targets" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-arm.Microsoft.Net.Native.SharedLibrary\$(DotNetNativeSharedLibrary)\build\runtime.win10-arm.Microsoft.Net.Native.SharedLibrary.targets" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-arm64.Microsoft.Net.Native.SharedLibrary\$(DotNetNativeSharedLibrary)\build\runtime.win10-arm64.Microsoft.Net.Native.SharedLibrary.targets" />
  <!-- End Custom .NET Native targets -->

Załaduj ponownie plik projektu w programie Visual Studio. W tym celu w Eksploratorze rozwiązań programu Visual Studio otwórz menu skrótów dla projektu CppToCSharpWinRT i wybierz Załaduj ponownie projekt.

Kompilowanie dla platformy .NET Native

Zaleca się skompilowanie i przetestowanie aplikacji przy użyciu składnika języka C# skompilowanych na platformie .NET Native. W programie Visual Studio otwórz menu skrótów dla projektu CppToCSharpWinRT i wybierz Odładuj projekt, aby otworzyć CppToCSharpWinRT.vcxproj w edytorze tekstu.

Następnie ustaw właściwość UseDotNetNativeToolchain na true w konfiguracjach Release i Arm64 w pliku projektu C++.

W Eksploratorze rozwiązań programu Visual Studio otwórz menu skrótów dla projektu CppToCSharpWinRT i wybierz Załaduj ponownie projekt.

  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
...
    <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Platform)'=='Arm64'" Label="Configuration">
    <UseDotNetNativeToolchain Condition="'$(UseDotNetNativeToolchain)'==''">true</UseDotNetNativeToolchain>
  </PropertyGroup>

Odwoływanie się do innych pakietów nuget języka C#

Jeśli składnik języka C# odwołuje się do innych pakietów NuGet , plik projektu aplikacji może wymagać uwzględnienia zależności plików z pakietu NuGet jako zawartości wdrożeniowej. Jeśli na przykład składnik języka C# odwołuje się do pakietu nuget Newtonsoft.Json, w projekcie aplikacji należy również odwołać się do tego samego pakietu nuget i zależności pliku.

W pliku SampleComponent.csproj dodaj odwołanie do pakietu NuGet:

    <PackageReference Include="Newtonsoft.Json">
      <Version>13.0.1</Version>
    </PackageReference>

W projekcie CppToCSharpWinRT znajdź plik packages.config i dodaj odpowiednie odniesienie NuGet. Spowoduje to zainstalowanie pakietu NuGet w folderze pakietu rozwiązania.

W packages.configdodaj to samo odwołanie do pakietu NuGet:

  <package id="Newtonsoft.Json" version="13.0.1" targetFramework="native" developmentDependency="true" />

Następnie dodaj następujący kod do pliku projektu aplikacji, aby odwołać się do odpowiedniej zależności pliku z folderu pakietu rozwiązania. Na przykład w CppToCSharpWinRT.vcxproj dodaj następujące elementy:

  <ItemGroup>
    <None Include="..\packages\Newtonsoft.Json.13.0.1\lib\netstandard2.0\Newtonsoft.Json.dll">
      <Link>%(Filename)%(Extension)</Link>
      <DeploymentContent>true</DeploymentContent>
    </None>
  </ItemGroup>