Använda winapp CLI med C++ och CMake

Den här guiden visar hur du använder winapp CLI med ett C++-program för att felsöka med paketidentitet och paketera ditt program som en MSIX.

Paketidentitet är ett grundläggande begrepp i Windows app modellen. Det gör att ditt program kan access specifika Windows-API:er (t.ex. meddelanden, säkerhet, AI-API:er osv.), har en ren installation/avinstallation med mera.

En körbar standard (som en som skapats med cmake --build) har inte paketidentitet. Den här guiden visar hur du lägger till den för felsökning och sedan paketera den för distribution.

Förutsättningar

  1. Byggverktyg: Använd en kompilatorverktygskedja som stöds av CMake. I det här exemplet används Visual Studio. Du kan installera community-utgåvan med:

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

    Starta om efter installationen.

  2. CMake: Installera CMake:

    winget install Kitware.CMake --source winget
    
  3. winapp CLI: Installera winapp CLI via winget:

    winget install Microsoft.winappcli --source winget
    

1. Skapa en ny C++-app

Börja med att skapa ett enkelt C++-program. Skapa en ny katalog för projekt.

mkdir cpp-app
cd cpp-app

Skapa en main.cpp fil med ett grundläggande "Hello, world!"-program:

#include <iostream>

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

Skapa en CMakeLists.txt fil för att konfigurera bygget:

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)

Skapa och kör den för att se till att allt fungerar:

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

2. Uppdatera koden för att kontrollera identiteten

Uppdatera appen för att kontrollera om den körs med paketidentitet med hjälp av Windows Runtime C++-API:et.

Uppdatera först din CMakeLists.txt för att länka till Windows App-modellbiblioteket:

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)

Ersätt sedan innehållet i 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. Kör utan identitet

Återskapa och kör appen:

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

Du bör se "Inte paketerad". Detta bekräftar att den körbara standarden körs utan paketidentitet.

4. Initiera project med winapp CLI

Kommandot winapp init konfigurerar allt du behöver: appmanifest, resurser och valfria Windows App SDK-huvudfiler för C++-utveckling.

winapp init

När du uppmanas att göra det:

  • Paketnamn: Tryck på Enter för att acceptera standardvärdet (cpp-app)
  • Utgivarens namn: Tryck på Enter för att acceptera standardvärdet eller ange ditt namn
  • Version: Tryck på Retur för att acceptera 1.0.0.0
  • Startpunkt: Tryck på Retur för att acceptera standardvärdet (cpp-app.exe)
  • Setup SDK:er: Välj "Stabila SDK:er" för att ladda ned Windows App SDK och generera rubriker

Det här kommandot skapar:

  • appxmanifest.xml och Assets mapp för din appidentitet
  • En .winapp mapp med Windows App SDK rubriker och bibliotek
  • En winapp.yaml konfigurationsfil för att fästa SDK-versioner

5. Felsöka med identitet

Om du vill testa funktioner som kräver identitet utan att helt paketera appen använder du winapp create-debug-identity:

  1. Skapa den körbara filen:

    cmake --build build --config Debug
    
  2. Använd felsökningsidentitet:

    winapp create-debug-identity .\build\Debug\cpp-app.exe
    
  3. Kör den körbara filen:

    .\build\Debug\cpp-app.exe
    

Nu bör du se utdata som liknar:

Package Family Name: cpp-app_12345abcde

Automatisera felsökningsidentitet (valfritt)

Lägg till ett post-build-kommando i din CMakeLists.txt för att automatiskt tillämpa felsökningsidentitet:

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. Använda Windows App SDK (valfritt)

Om du har valt att installera SDK:erna under winapp init har du åtkomst till Windows App SDK-rubrikerna i mappen .winapp/include.

Uppdatera din CMakeLists.txt för att inkludera rubrikerna:

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

Uppdatera main.cpp för att använda api:et Windows App Runtime:

#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. Återställ rubriker när det behövs

Mappen .winapp läggs automatiskt till i .gitignore. När andra klonar din project måste de återställa dessa filer:

winapp restore
winapp cert generate --if-exists skip

8. Paket med MSIX

När du är redo att distribuera paketera du som MSIX:

  1. Skapa för lansering:

    cmake --build build --config Release
    
  2. Förberedelse av en paketkatalog:

    mkdir dist
    copy .\build\Release\cpp-app.exe .\dist\
    
  3. Generera ett utvecklingscertifikat:

    winapp cert generate --if-exists skip
    
  4. Paketera och signera:

    winapp pack .\dist --cert .\devcert.pfx
    
  5. Installera certifikatet (kör som administratör):

    winapp cert install .\devcert.pfx
    
  6. Installera och kör:

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

Tips/Råd

  • Signera din MSIX med ett kodsigneringscertifikat från en certifikatutfärdare för produktionsdistribution.
  • Microsoft Store signerar MSIX åt dig, du behöver inte signera innan det skickas in.
  • Du kan behöva separata MSIX-paket för varje arkitektur som du stöder (x64, Arm64).