Criar pacotes UWP

A UWP (Plataforma Universal do Windows) fornece uma plataforma de aplicativo comum para todos os dispositivos que são executados no Windows 10. Nesse modelo, os aplicativos UWP podem chamar APIs do WinRT que são comuns a todos os dispositivos e APIs (incluindo Win32 e .NET) que são específicas para a família do dispositivo no qual o aplicativo está em execução.

Neste passo a passo, você cria um pacote NuGet com um componente UWP nativo (incluindo um controle XAML) que pode ser usado em projetos nativos e gerenciados.

Pré-requisitos

  1. Visual Studio 2017 ou 2015. Instale a edição Community 2017 gratuitamente no visualstudio.com; você também pode usar as edições Professional e Enterprise.

  2. CLI do NuGet. Baixe a versão mais recente do nuget.exe de nuget.org/downloads e salve-a em um local de sua escolha (o download é o .exe diretamente). Em seguida, adicione tal local à sua variável de ambiente PATH, se ainda não tiver feito isso.

Criar um componente do Windows Runtime da UWP

  1. Em Visual Studio, escolha Arquivo > Novo > Project, expanda o nó Visual C++ > Windows > Universal, selecione o modelo Windows Runtime Component (Universal Windows), altere o nome para ImageEnhancer e clique em OK. Aceite os valores padrão para a Versão de Destino e a Versão Mínima quando solicitado.

    Creating a new UWP Windows Runtime Component project

  2. Clique com o botão direito do mouse no projeto no Gerenciador de Soluções, selecione Adicionar > Novo Item, clique no nó XAML do Visual C++>, selecione Controle De modelo, altere o nome para AwesomeImageControl.cpp e clique em Adicionar:

    Adding a new XAML Templated Control item to the project

  3. Clique com o botão direito do mouse no projeto em Gerenciador de Soluções e selecione Propriedades. Na página Propriedades, expanda as Propriedades > de Configuração C/C++ e clique em Arquivos de Saída. No painel à direita, altere o valor para Gerar arquivos de documentação XML para Sim:

    Setting Generate XML Documentation Files to Yes

  4. Clique com botão direito do mouse na solução agora, selecione Build em Lotes e marque as três caixas de Depuração na caixa de diálogo, conforme mostrado abaixo. Isso garante que, quando você fizer uma compilação, gerará um conjunto completo de artefatos para cada um dos sistemas de destino com os quais o Windows é compatível.

    Batch Build

  5. Na caixa de diálogo Compilação em Lotes, clique em Compilar para confirmar o projeto e criar os arquivos de saída que você precisa para o pacote NuGet.

Observação

Neste passo a passo, você usará os artefatos de Depuração para o pacote. Para o pacote sem depuração, marque as opções de Versão na caixa de diálogo de Build em Lotes e consulte as pastas de Versão resultantes nas etapas a seguir.

Criar e atualizar o arquivo .nuspec

Para criar o arquivo .nuspec inicial, execute as três etapas abaixo. As seções a seguir, em seguida, guiarão você pelas outras atualizações necessárias.

  1. Abra um prompt de comando e navegue até a pasta que contém ImageEnhancer.vcxproj (essa será uma subpasta abaixo onde está o arquivo da solução).

  2. Execute o comando spec do NuGet para gerar ImageEnhancer.nuspec (o nome do arquivo é obtido do nome do arquivo .vcxproj):

    nuget spec
    
  3. Abra o ImageEnhancer.nuspec em um editor e atualize-o para corresponder ao seguinte, substituindo YOUR_NAME por um valor apropriado. O valor <id>, especificamente, precisa ser exclusivo no nuget.org (consulte as convenções de nomenclatura descritas em Criando um pacote). Observe que você também precisa atualizar as marcas de autor e descrição ou um erro é mostrado durante a etapa de empacotamento.

    <?xml version="1.0"?>
    <package >
        <metadata>
        <id>ImageEnhancer.YOUR_NAME</id>
        <version>1.0.0</version>
        <title>ImageEnhancer</title>
        <authors>YOUR_NAME</authors>
        <owners>YOUR_NAME</owners>
        <requireLicenseAcceptance>false</requireLicenseAcceptance>
        <description>Awesome Image Enhancer</description>
        <releaseNotes>First release</releaseNotes>
        <copyright>Copyright 2016</copyright>
        <tags>image enhancer imageenhancer</tags>
        </metadata>
    </package>
    

Observação

Para pacotes compilados para consumo público, preste atenção especial ao elemento <tags>, visto que essas marcas ajudam outras pessoas a localizar o pacote e entender o que ele faz.

Adicionar metadados do Windows ao pacote

Um componente do Windows Runtime requer metadados que descrevem todos os seus tipos disponíveis publicamente, o que possibilita outros aplicativos e bibliotecas a consumirem o componente. Esses metadados estão contidos em um arquivo .winmd, que é criado quando você compila o projeto e precisa ser incluído em seu pacote do NuGet. Um arquivo XML com os dados do IntelliSense também é criado ao mesmo tempo e também deve ser incluído.

Adicione o nó <files> a seguir ao arquivo .nuspec:

<package>
    <metadata>
        ...
    </metadata>

    <files>
        <!-- WinMd and IntelliSense files -->
        <file src="..\Debug\ImageEnhancer\ImageEnhancer.winmd" target="lib\uap10.0"/>
        <file src="..\Debug\ImageEnhancer\ImageEnhancer.xml" target="lib\uap10.0"/>
    </files>
</package>

Adicionar conteúdo XAML

Para incluir um controle XAML no seu componente, você precisa adicionar o arquivo XAML que tem o modelo padrão para o controle (conforme gerado pelo modelo de projeto). Isso também vai para a seção <files>:

<?xml version="1.0"?>
<package >
    <metadata>
        ...
    </metadata>
    <files>
        ...

        <!-- XAML controls -->
        <file src="Themes\Generic.xaml" target="lib\uap10.0\Themes"/>

    </files>
</package>

Adicionar as bibliotecas de implementação nativa

No seu componente, a lógica principal do tipo ImageEnhancer está no código nativo, que está contido nos vários assemblies ImageEnhancer.dll que são gerados para cada runtime de destino(ARM, x86 e x64). Para incluí-los no pacote, faça referência a eles na seção <files> juntamente com seus arquivos de recurso .pri associado:

<?xml version="1.0"?>
<package >
    <metadata>
        ...
    </metadata>
    <files>
        ...

        <!-- DLLs and resources -->
        <file src="..\ARM\Debug\ImageEnhancer\ImageEnhancer.dll" target="runtimes\win10-arm\native"/>
        <file src="..\ARM\Debug\ImageEnhancer\ImageEnhancer.pri" target="runtimes\win10-arm\native"/>

        <file src="..\ARM64\Debug\ImageEnhancer\ImageEnhancer.dll" target="runtimes\win10-arm64\native"/>
        <file src="..\ARM64\Debug\ImageEnhancer\ImageEnhancer.pri" target="runtimes\win10-arm64\native"/>

        <file src="..\x64\Debug\ImageEnhancer\ImageEnhancer.dll" target="runtimes\win10-x64\native"/>
        <file src="..\x64\Debug\ImageEnhancer\ImageEnhancer.pri" target="runtimes\win10-x64\native"/>

        <file src="..\Debug\ImageEnhancer\ImageEnhancer.dll" target="runtimes\win10-x86\native"/>
        <file src="..\Debug\ImageEnhancer\ImageEnhancer.pri" target="runtimes\win10-x86\native"/>

    </files>
</package>

Adicionar .targets

Em seguida, projetos C++ e JavaScript que podem consumir seu pacote do NuGet precisam de um arquivo .targets para identificar os arquivos de assembly e winmd necessários. (Projetos C# e Visual Basic fazem isso automaticamente.) Crie esse arquivo copiando o texto abaixo ImageEnhancer.targets e salvando-o na mesma pasta que o .nuspec arquivo. Observação: esse arquivo .targets precisa ter o mesmo nome que a ID do pacote (por exemplo, o elemento <Id> no arquivo .nupspec):

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <ImageEnhancer-Platform Condition="'$(Platform)' == 'Win32'">x86</ImageEnhancer-Platform>
        <ImageEnhancer-Platform Condition="'$(Platform)' != 'Win32'">$(Platform)</ImageEnhancer-Platform>
    </PropertyGroup>
    <ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'UAP'">
        <Reference Include="$(MSBuildThisFileDirectory)..\..\lib\uap10.0\ImageEnhancer.winmd">
            <Implementation>ImageEnhancer.dll</Implementation>
        </Reference>
    <ReferenceCopyLocalPaths Include="$(MSBuildThisFileDirectory)..\..\runtimes\win10-$(ImageEnhancer-Platform)\native\ImageEnhancer.dll" />
    </ItemGroup>
</Project>

Em seguida, consulte ImageEnhancer.targets no seu arquivo .nuspec:

<?xml version="1.0"?>
<package >
    <metadata>
        ...
    </metadata>
    <files>
        ...

        <!-- .targets -->
        <file src="ImageEnhancer.targets" target="build\native"/>

    </files>
</package>

.nuspec final

O arquivo .nuspec final agora deve ser semelhante ao seguinte, em que novamente YOUR_NAME deve ser substituído por um valor apropriado:

<?xml version="1.0"?>
<package >
    <metadata>
    <id>ImageEnhancer.YOUR_NAME</id>
    <version>1.0.0</version>
    <title>ImageEnhancer</title>
    <authors>YOUR_NAME</authors>
    <owners>YOUR_NAME</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Awesome Image Enhancer</description>
    <releaseNotes>First Release</releaseNotes>
    <copyright>Copyright 2016</copyright>
    <tags>image enhancer imageenhancer</tags>
    </metadata>
    <files>
    <!-- WinMd and IntelliSense -->
    <file src="..\Debug\ImageEnhancer\ImageEnhancer.winmd" target="lib\uap10.0"/>
    <file src="..\Debug\ImageEnhancer\ImageEnhancer.xml" target="lib\uap10.0"/>

    <!-- XAML controls -->
    <file src="Themes\Generic.xaml" target="lib\uap10.0\Themes"/>

    <!-- DLLs and resources -->
    <file src="..\ARM\Debug\ImageEnhancer\ImageEnhancer.dll" target="runtimes\win10-arm\native"/>
    <file src="..\ARM\Debug\ImageEnhancer\ImageEnhancer.pri" target="runtimes\win10-arm\native"/>
    <file src="..\ARM64\Debug\ImageEnhancer\ImageEnhancer.dll" target="runtimes\win10-arm64\native"/>
    <file src="..\ARM64\Debug\ImageEnhancer\ImageEnhancer.pri" target="runtimes\win10-arm64\native"/>     
    <file src="..\x64\Debug\ImageEnhancer\ImageEnhancer.dll" target="runtimes\win10-x64\native"/>
    <file src="..\x64\Debug\ImageEnhancer\ImageEnhancer.pri" target="runtimes\win10-x64\native"/>
    <file src="..\Debug\ImageEnhancer\ImageEnhancer.dll" target="runtimes\win10-x86\native"/>
    <file src="..\Debug\ImageEnhancer\ImageEnhancer.pri" target="runtimes\win10-x86\native"/>

    <!-- .targets -->
    <file src="ImageEnhancer.targets" target="build\native"/>

    </files>
</package>

Empacotar o componente

Depois do .nuspec terminar de referenciar todos os arquivos que você precisa incluir no pacote, você estará pronto para executar o comando pack:

nuget pack ImageEnhancer.nuspec

Isso gera ImageEnhancer.YOUR_NAME.1.0.0.nupkg. Ao abrir este arquivo em uma ferramenta como o Explorador de Pacotes NuGet e expandir todos os nós, você verá o seguinte conteúdo:

NuGet Package Explorer showing the ImageEnhancer package

Dica

O arquivo .nupkg é apenas um arquivo ZIP com uma extensão diferente. Também é possível examinar o conteúdo do pacote alterando .nupkg para .zip, mas lembre-se de restaurar a extensão antes de carregar um pacote para o nuget.org.

Para disponibilizar seu pacote para outros desenvolvedores, siga as instruções sobre Publicar um pacote.