Partilhar via


Usar a linha de comando winapp com C++ e CMake

Este guia demonstra como usar a linha de comando winapp com uma aplicação C++ para depurar com identidade de pacote e empacotar a sua aplicação como MSIX.

A identidade de pacote é um conceito central no modelo de Windows app. Permite que a sua aplicação acesse APIs específicas do Windows (como Notificações, Segurança, APIs de IA, etc.), tenha uma experiência limpa de instalação/desinstalação e muito mais.

Um executável padrão (como um criado com cmake --build) não tem identidade de pacote. Este guia mostra como adicioná-lo para depuração e depois empacotar para distribuição.

Pré-requisitos

  1. Ferramentas de Build: Use uma cadeia de ferramentas de compiladores suportada pelo CMake. Este exemplo utiliza o Visual Studio. Pode instalar a edição comunitária com:

    winget install --id Microsoft.VisualStudio.Community --source winget --override "--add Microsoft.VisualStudio.Workload.NativeDesktop --includeRecommended --passive --wait"
    

    Reinicia após a instalação.

  2. CMake: Instalar CMake:

    winget install Kitware.CMake --source winget
    
  3. Winapp CLI: Instale a winapp CLI via winget:

    winget install Microsoft.winappcli --source winget
    

1. Criar uma nova aplicação C++

Comece por criar uma aplicação simples em C++. Crie um novo diretório para o seu projecto:

mkdir cpp-app
cd cpp-app

Crie um main.cpp ficheiro com um programa básico de "Olá, mundo!":

#include <iostream>

int main() {
    std::cout << "Hello, world!" << std::endl;
    return 0;
}

Crie um CMakeLists.txt ficheiro para configurar a build:

cmake_minimum_required(VERSION 3.20)
project(cpp-app)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(cpp-app main.cpp)

Constrói e executa para garantir que tudo está a funcionar:

cmake -B build
cmake --build build --config Debug
.\build\Debug\cpp-app.exe

2. Atualizar código para verificar identidade

Atualize a aplicação para verificar se está a correr com a identidade do pacote usando a API C++ do Windows Runtime.

Primeiro, atualize o seu CMakeLists.txt para ligar à biblioteca Windows App Model:

cmake_minimum_required(VERSION 3.20)
project(cpp-app)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(cpp-app main.cpp)

# Link Windows Runtime libraries
target_link_libraries(cpp-app PRIVATE WindowsApp.lib OneCoreUap.lib)

De seguida, substitua o conteúdo de main.cpp:

#include <iostream>
#include <windows.h>
#include <appmodel.h>

int main() {
    UINT32 length = 0;
    LONG result = GetCurrentPackageFamilyName(&length, nullptr);

    if (result == ERROR_INSUFFICIENT_BUFFER) {
        std::wstring familyName;
        familyName.resize(length);

        result = GetCurrentPackageFamilyName(&length, familyName.data());

        if (result == ERROR_SUCCESS) {
            std::wcout << L"Package Family Name: " << familyName.c_str() << std::endl;
        } else {
            std::wcout << L"Error retrieving Package Family Name" << std::endl;
        }
    } else {
        std::cout << "Not packaged" << std::endl;
    }

    return 0;
}

3. Fugir sem identidade

Reconstrua e execute a aplicação:

cmake --build build --config Debug
.\build\Debug\cpp-app.exe

Deves ver "Não embalado". Isto confirma que o executável padrão está a correr sem qualquer identidade de pacote.

4. Inicialize o projeto com o winapp CLI

O comando winapp init define tudo o que precisas: manifesto da app, assets e, opcionalmente, cabeçalhos Windows App SDK para desenvolvimento em C++.

winapp init

Quando solicitado:

  • Nome do pacote: Pressione Enter para aceitar o padrão (cpp-app)
  • Nome do Publicador: Pressione Enter para aceitar o padrão ou inserir o seu nome
  • Versão: Pressione Enter para aceitar 1.0.0.0
  • Ponto de entrada: Pressione Enter para aceitar o padrão (cpp-app.exe)
  • Setup SDKs: Selecione "Stable SDKs" para descarregar Windows App SDK e gerar cabeçalhos

Este comando cria:

  • appxmanifest.xml e Assets pasta para a identidade da sua app
  • Uma pasta .winapp com cabeçalhos e bibliotecas Windows App SDK
  • Um winapp.yaml ficheiro de configuração para definir versões do SDK

5. Depuração com identidade

Para testar funcionalidades que requerem identidade sem embalar totalmente a aplicação, use winapp create-debug-identity:

  1. Constrói o executável:

    cmake --build build --config Debug
    
  2. Aplicar identidade de depuração:

    winapp create-debug-identity .\build\Debug\cpp-app.exe
    
  3. Execute o executável:

    .\build\Debug\cpp-app.exe
    

Agora deverá ver uma saída semelhante a:

Package Family Name: cpp-app_12345abcde

Automatização da identidade de depuração (opcional)

Adicione um comando pós-compilação ao seu CMakeLists.txt para aplicar automaticamente a identidade de depuração:

add_custom_command(TARGET cpp-app POST_BUILD
    COMMAND $<$<CONFIG:Debug>:winapp>
            $<$<CONFIG:Debug>:create-debug-identity>
            $<$<CONFIG:Debug>:$<TARGET_FILE:cpp-app>>
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
    COMMAND_EXPAND_LISTS
    COMMENT "Applying debug identity to executable..."
)

6. Utilização do Windows App SDK (opcional)

Se optaste por configurar os SDKs durante winapp init, tens acesso aos cabeçalhos do Windows App SDK na pasta .winapp/include.

Atualize o seu CMakeLists.txt de modo a incluir os cabeçalhos:

# Add Windows App SDK include directory
target_include_directories(cpp-app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/.winapp/include)

Atualize main.cpp para utilizar a API de Tempo de Execução do App Windows.

#include <iostream>
#include <windows.h>
#include <appmodel.h>
#include <winrt/Microsoft.Windows.ApplicationModel.WindowsAppRuntime.h>

int main() {
    winrt::init_apartment();

    UINT32 length = 0;
    LONG result = GetCurrentPackageFamilyName(&length, nullptr);

    if (result == ERROR_INSUFFICIENT_BUFFER) {
        std::wstring familyName;
        familyName.resize(length);

        result = GetCurrentPackageFamilyName(&length, familyName.data());

        if (result == ERROR_SUCCESS) {
            std::wcout << L"Package Family Name: " << familyName.c_str() << std::endl;

            auto runtimeVersion = winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::RuntimeInfo::AsString();
            std::wcout << L"Windows App Runtime Version: " << runtimeVersion.c_str() << std::endl;
        }
    } else {
        std::cout << "Not packaged" << std::endl;
    }

    return 0;
}

7. Restaurar cabeçalhos quando necessário

A .winapp pasta é automaticamente adicionada a .gitignore. Quando outros clonam o seu projecto, precisam de restaurar estes ficheiros:

winapp restore
winapp cert generate --if-exists skip

8. Pacote com MSIX

Quando estiver pronto para distribuir, embale como MSIX:

  1. Build para lançamento:

    cmake --build build --config Release
    
  2. Prepare o diretório de pacotes:

    mkdir dist
    copy .\build\Release\cpp-app.exe .\dist\
    
  3. Gerar um certificado de desenvolvimento:

    winapp cert generate --if-exists skip
    
  4. Embalagem e assinatura:

    winapp pack .\dist --cert .\devcert.pfx
    
  5. Instalar o certificado (executar como administrador):

    winapp cert install .\devcert.pfx
    
  6. Instalar e executar:

    Add-AppxPackage .\cpp-app.msix
    cpp-app
    

Sugestão

  • Assine o seu MSIX com um certificado de assinatura de código de uma Autoridade Certificadora para distribuição em produção.
  • A Microsoft Store assina o MSIX por si, não precisa de assinar antes de submeter.
  • Podes precisar de pacotes MSIX separados para cada arquitetura que suportas (x64, Arm64).