Compartilhar via


Criando um componente do Windows Runtime em C# para uso em um aplicativo C++/WinRT

Este tópico explica o processo de adição de um componente C# simples ao seu projeto C++/WinRT.

O Visual Studio facilita a criação e a implantação de seus próprios tipos personalizados do Windows Runtime dentro de um projeto WRC (componente do Windows Runtime) escrito com C# ou Visual Basic, e, em seguida, permite que você referencie esse WRC em um projeto de aplicativo C++ e consuma esses tipos personalizados a partir desse aplicativo.

Internamente, os tipos do Windows Runtime podem usar qualquer funcionalidade do .NET permitida em um aplicativo UWP.

Observação

Para obter mais informações, consulte componentes do Windows Runtime com C# e Visual Basic e .NET para aplicativos UWP.

Externamente, os membros do seu tipo podem expor apenas os tipos do Windows Runtime para seus parâmetros e retornar valores. Quando você cria sua solução, o Visual Studio cria seu projeto .NET WRC e, em seguida, executa uma etapa de build que cria um arquivo de metadados do Windows (.winmd). Esse é o WRC (componente do Windows Runtime), que o Visual Studio inclui em seu aplicativo.

Observação

O .NET mapeia automaticamente alguns tipos .NET comumente usados, como tipos de dados primitivos e tipos de coleta, para seus equivalentes do Windows Runtime. Esses tipos .NET podem ser usados na interface pública de um componente do Windows Runtime e aparecerão para os usuários do componente como os tipos correspondentes do Windows Runtime. Consulte componentes do Windows Runtime comC# e Visual Basic.

Pré-requisitos

Criar um aplicativo em branco

No Visual Studio, crie um novo projeto usando o modelo de projeto Aplicativo em Branco (C++/WinRT). Verifique se você está usando o modelo (C++/WinRT), e não o do (Windows universal).

Defina o nome do novo projeto como CppToCSharpWinRT para que sua estrutura de pastas corresponda ao passo a passo.

Adicionar um componente do Windows Runtime em C# à solução

No Visual Studio, crie o projeto de componente: no Gerenciador de Soluções, abra o menu de atalho para a solução CppToCSharpWinRT e escolha Adicionar e escolha Novo Projeto para adicionar um novo projeto C# à solução. Na seção Modelos Instalados da caixa de diálogo Adicionar Novo Projeto, escolha Visual C#, em seguida, escolha Windows, e, em seguida, Universal. Escolha o modelo Componente do Windows Runtime (Universal do Windows) e insira SampleComponent como o nome do projeto.

Observação

Na caixa de diálogo Novo Projeto de Plataforma Universal do Windows, escolha Windows 10 Creators Update (10.0; Build 15063) como a versão mínima. Consulte a seção Versão Mínima do Aplicativo abaixo para obter mais informações.

Adicionar o método GetMyString em C#

No projeto SampleComponent , altere o nome da classe de Classe1 para Exemplo. Em seguida, adicione dois membros simples à classe, um campo privado int e um método de instância chamado GetMyString:

    public sealed class Example
    {
        int MyNumber;

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

Observação

Por padrão, a classe é marcada público lacrado . Todas as classes do Windows Runtime que você expõe do componente devem ser lacradas.

Observação

Opcional: Para habilitar o IntelliSense para os membros recém-adicionados, no Gerenciador de Soluções, abra o menu de atalho do projeto SampleComponent e escolha Compilar.

Referenciar o SampleComponent em C# do projeto CppToCSharpWinRT

No Gerenciador de Soluções, no projeto C++/WinRT, abra o menu de atalho para Referências e escolha Adicionar Referência para abrir a caixa de diálogo Adicionar Referência . Escolha Projetose, em seguida, escolha Solução. Marque a caixa de seleção do projeto SampleComponent e escolha OK para adicionar uma referência.

Observação

Opcional: Para habilitar o IntelliSense para o projeto C++/WinRT, no Gerenciador de Soluções, abra o menu de atalho do projeto CppToCSharpWinRT e escolha Compilar.

Editar MainPage.h

Abra no projeto de CppToCSharpWinRT e adicione dois itens. Primeiro adicione #include "winrt/SampleComponent.h" no final das declarações #include, depois um campo winrt::SampleComponent::Example na struct MainPage.

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

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

Observação

No Visual Studio, MainPage.h está listado em MainPage.xaml.

Editar MainPage.cpp

No MainPage.cpp, altere a implementação de Mainpage::ClickHandler para chamar o método C# GetMyString.

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

    hstring myString = myExample.GetMyString();

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

Executar o projeto

Agora você pode compilar e executar o projeto. Cada vez que você clicar no botão, o número no botão será incrementado.

C++/WinRT Windows chamando uma captura de tela do componente C#

Dica

No Visual Studio, crie o projeto de componente: no Gerenciador de Soluções, abra o menu de atalho do projeto CppToCSharpWinRT e escolha Propriedadese escolha de Depuração em Propriedades de Configuração. Defina o Tipo de Depurador como Gerenciado e Nativo se desejar depurar o código C# (gerenciado) e C++ (nativo). propriedades de depuração C++

Versão mínima do aplicativo

O mínimo de aplicação da versão do projeto em C# controlará a versão do .NET usada para compilar a aplicação. Por exemplo, escolher Windows 10 Fall Creators Update (10.0; Build 16299) ou posterior habilitará o suporte ao .NET Standard 2.0 e ao processador Windows Arm64.

Dica

É recomendável usar as versões mínimas de do aplicativo inferiores a 16299 para evitar a configuração de build extra se o suporte ao .NET Standard 2.0 ou Arm64 não for necessário.

Configurar para o Windows 10 Fall Creators Update (10.0; Build 16299)

Siga estas etapas para habilitar o suporte ao .NET Standard 2.0 ou ao Windows Arm64 nos projetos em C# referenciados do seu projeto C++/WinRT.

No Visual Studio, acesse o Gerenciador de Soluções e abra o menu de atalho do projeto CppToCSharpWinRT . Escolha Propriedades e defina a versão Universal do Windows App Min como Windows 10 Fall Creators Update (10.0; Build 16299) (ou superior). Faça o mesmo para o projeto SampleComponent.

No Visual Studio, abra o menu de atalho do projeto CppToCSharpWinRT e escolha Descarregar Projeto para abrir o projeto CppToCSharpWinRT.vcxproj no editor de texto.

Copie e cole o XML a seguir no primeiro PropertyGroup em 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 -->

Os valores para DotNetNativeVersion, DotNetNativeSharedLibrarye UWPCoreRuntimeSdkVersion podem variar dependendo da versão do Visual Studio. Para defini-los com os valores corretos, abra %ProgramFiles(x86)%\Microsoft SDKs\UWPNuGetPackages e examine o subdiretório para cada valor na tabela abaixo. O %ProgramFiles(x86)%\Microsoft SDKs\UWPNuGetPackages\Microsoft.Net.Native.Compiler diretório terá um subdiretório que contém uma versão instalada do .NET native que começa com 2.2. No exemplo abaixo, é 2.2.12-rel-31116-00.

Variável MSBuild Diretório Exemplo
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

Observação

Há várias arquiteturas com suporte para Microsoft.Net.Native.SharedLibrary. Substitua x64 pela arquitetura apropriada. Por exemplo, a arm64 arquitetura estaria no %ProgramFiles(x86)%\Microsoft SDKs\UWPNuGetPackages\runtime.win10-arm64.microsoft.net.native.sharedlibrary diretório.

Em seguida, imediatamente após o primeiro PropertyGroup, adicione o seguinte (sem alterações).

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

No final do arquivo de projeto, pouco antes do fechamento da tag Project, adicione o seguinte (inalterado).

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

Recarregue o arquivo de projeto no Visual Studio. Para fazer isso, no Gerenciador de Soluções do Visual Studio, abra o menu de atalho do projeto CppToCSharpWinRT do e escolha Recarregar o Projeto.

Compilando para o .NET Native

É recomendável criar e testar seu aplicativo com o componente C# compilado para .NET native. No Visual Studio, abra o menu de atalho do projeto CppToCSharpWinRT e escolha Descarregar Projeto para abrir o projeto CppToCSharpWinRT.vcxproj no editor de texto.

Em seguida, nas configurações de Versão e Arm64, defina a propriedade UseDotNetNativeToolchain para true no arquivo de projeto C++.

No Gerenciador de Soluções do Visual Studio, abra o menu de atalho do projeto de CppToCSharpWinRT do e escolha Recarregar o Projeto.

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

Referenciando outros pacotes NuGet em C#

Se o componente C# estiver fazendo referência a outras pacotes nuget, o arquivo de projeto do aplicativo poderá precisar de dependências de arquivo de lista do pacote nuget como conteúdo de implantação. Por exemplo, se o componente C# fizer referência ao pacote nuget Newtonsoft.Json, o mesmo pacote nuget e a dependência de arquivo também deverão ser referenciados no projeto do aplicativo.

No arquivo SampleComponent.csproj , adicione a referência do pacote nuget:

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

No projeto CppToCSharpWinRT, localize o arquivo packages.config e adicione a referência de NuGet apropriada. Isso instalará o pacote nuget na pasta do pacote da solução.

Em packages.config, adicione a mesma referência de pacote nuget:

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

Em seguida, adicione o seguinte ao arquivo de projeto do aplicativo para fazer referência à dependência de arquivo apropriada do diretório de pacotes da solução. Por exemplo, em CppToCSharpWinRT.vcxproj adicione o seguinte:

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