Partilhar via


Criação de um componente do Tempo de Execução do Windows em C# para uso em um aplicativo C++/WinRT

Este tópico orienta você pelo 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 Tempo de Execução do Windows dentro de um projeto WRC (componente do Tempo de Execução do Windows) escrito com C# ou Visual Basic e, em seguida, fazer referência a esse WRC de um projeto de aplicativo C++ e consumir esses tipos personalizados desse aplicativo.

Internamente, seus tipos do Tempo de Execução do Windows podem usar qualquer funcionalidade .NET permitida em um aplicativo UWP.

Observação

Para obter mais informações, consulte Componentes do Tempo de Execução do Windows com C# e Visual Basic e a Visão Geral do .NET para aplicações UWP.

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

Observação

O .NET mapeia automaticamente alguns tipos .NET comumente usados, como tipos de dados primitivos e tipos de coleção, para seus equivalentes do Tempo de Execução do Windows. Esses tipos .NET podem ser usados na interface pública de um componente do Windows Runtime e serão apresentados aos utilizadores do componente como os tipos correspondentes do Windows Runtime. Veja componentes de Tempo de Execução do Windows com C# e Visual Basic.

Pré-requisitos

Criar um aplicativo em branco

No Visual Studio, crie um novo projeto usando o Aplicativo em Branco (C++/WinRT) modelo de projeto. Certifique-se de que está a usar o modelo (C++/WinRT) e não o modelo (Universal Windows).

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

Adicionar um componente de Tempo de Execução do Windows em C# à solução

No Visual Studio, crie o projeto do componente: No Gerenciador de Soluções, abra o menu de atalho para a solução CppToCSharpWinRT e escolha Adicionare, em seguida, 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#, depois escolha Windowse depois Universal. Escolha o modelo Componente do Tempo de Execução do Windows (Universal Windows) e insira SampleComponent para o nome do projeto.

Observação

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

Adicione o método C# GetMyString

No projeto SampleComponent, altere o nome da classe de Class1 para Exemplo. Em seguida, adicione dois membros simples à classe, um campo de int privado 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ública selada. Todas as classes do Tempo de Execução do Windows que você expõe do seu componente devem estar seladas.

Observação

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

Faça referência ao C# SampleComponent do projeto CppToCSharpWinRT

No Gestor de Soluções, no projeto C++/WinRT, abra o menu de atalho de Referências para e escolha Adicionar Referência para abrir a caixa de diálogo Adicionar Referência . Escolha Projetose depois escolha Solução. Marque a caixa de verificaçã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 para o projeto CppToCSharpWinRT e escolha Build.

Editar MainPage.h

Abra MainPage.h no projeto CppToCSharpWinRT e, em seguida, adicione dois itens. Primeiro, adicione #include "winrt/SampleComponent.h" no final das instruções #include, depois um campo winrt::SampleComponent::Example à estrutura 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 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 criar e executar o projeto. Cada vez que você clicar no botão, o número no botão irá aumentar.

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

Sugestão

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

Versão mínima do aplicativo

A Aplicação Mínima da versão do projeto C# controlará a versão do .NET usada para compilar o aplicativo. Por exemplo, escolher Windows 10 Fall Creators Update (10.0; Build 16299) ou posterior habilitará o .NET Standard 2.0 e o suporte ao processador Windows Arm64.

Sugestão

Recomendamos o uso de Application Minimum versões inferiores a 16299 para evitar a configuração de compilação extra se o suporte ao .NET Standard 2.0 ou Arm64 não for necessário.

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

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

No Visual Studio, vá para o Explorador de Soluções e abra o menu de atalho para o projeto CppToCSharpWinRT. Escolha Propriedades e defina a versão Universal 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 para o projeto CppToCSharpWinRT e escolha Descarregar Projeto para abrir CppToCSharpWinRT.vcxproj no editor de texto.

Copie e cole o seguinte XML para o primeiro PropertyGroup no 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 o %ProgramFiles(x86)%\Microsoft SDKs\UWPNuGetPackages e examine o subdiretório para cada valor na tabela abaixo. O diretório %ProgramFiles(x86)%\Microsoft SDKs\UWPNuGetPackages\Microsoft.Net.Native.Compiler terá um subdiretório que contém uma versão instalada do .NET nativo 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 suportadas para Microsoft.Net.Native.SharedLibrary. Substitua x64 pela arquitetura apropriada. Por exemplo, a arquitetura arm64 estaria no diretório %ProgramFiles(x86)%\Microsoft SDKs\UWPNuGetPackages\runtime.win10-arm64.microsoft.net.native.sharedlibrary.

Em seguida, imediatamente após a primeira 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, imediatamente antes do fechamento Project tag, 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 contexto para o projeto CppToCSharpWinRT e escolha Recarregar Projeto.

Desenvolvendo para .NET Native

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

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

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

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

Fazendo referência a outros pacotes NuGet em C#

Se o componente C# estiver fazendo referência a outros pacotes nuget, o arquivo de projeto do aplicativo pode 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 mesma dependência de arquivo também deverão ser referenciados no projeto de 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 ficheiro packages.config e adicione a referência nuget apropriada. Isso instalará o pacote nuget na pasta de pacotes da solução.

No packages.config, adicione a mesma referência do pacote nuget:

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

Em seguida, adicione o código seguinte ao ficheiro de projeto da aplicação para fazer referência à dependência de ficheiro adequada da pasta 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>