Winapp CLI használata C++ és CMake használatával

Ez az útmutató bemutatja, hogyan használhatja a winapp parancssori felületet egy C++ alkalmazással a csomagdentitás hibakereséséhez és az alkalmazás MSIX-ként való becsomagolásához.

A csomagidentitás a Windows app modell alapvető fogalma. Lehetővé teszi, hogy az alkalmazás hozzáférjen bizonyos Windows API-khoz (például értesítések, biztonság, AI API-k stb.), tiszta telepítési/eltávolítási felülettel rendelkezik, és így tovább.

Egy standard végrehajtható fájl (mint amilyet a cmake --build-vel hoznak létre) nem rendelkezik csomagidentitással. Ez az útmutató bemutatja, hogyan lehet egy elemet hozzáadni hibakereséshez, majd hogyan csomagolhatja be terjesztés céljából.

Előfeltételek

  1. Build tools: A CMake által támogatott fordítóeszközlánc használata. Ez a példa Visual Studio használ. A közösségi kiadást telepítheti (vagy frissítheti, ha már telepítve van):

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

    A telepítés után újraindul.

  2. CMake: A CMake telepítése (vagy frissítés, ha már telepítve van):

    winget install Kitware.CMake --source winget
    
  3. winapp parancssori felület: Telepítse a parancssori felületet a winapp wingeten keresztül (vagy frissítse, ha már telepítve van):

    winget install Microsoft.winappcli --source winget
    

1. Új C++ alkalmazás létrehozása

Először hozzon létre egy egyszerű C++ alkalmazást. Hozzon létre egy új mappát a projekt számára:

mkdir cpp-app
cd cpp-app

Hozzon létre egy main.cpp fájlt egy alapszintű "Hello, world!" programmal:

#include <iostream>

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

Hozzon létre egy CMakeLists.txt fájlt a build konfigurálásához:

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)

Fordítsa le és futtassa, és győződjön meg róla, hogy minden működik.

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

A kimenetnek a következőnek kell lennie: "Hello, world!"

2. Kód frissítése az identitás ellenőrzéséhez

Frissítjük az alkalmazást, hogy ellenőrizze, a csomagazonossággal fut-e. Ez segít ellenőrizni, hogy az identitás megfelelően működik-e a későbbi lépésekben. A Windows-futtatókörnyezet C++ API-val fogjuk elérni a Csomag API-kat.

Először adja hozzá a következő sort a CMakeLists.txt végéhez a Windows-alkalmazás Modell kódtárhoz való csatoláshoz:

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

Ezután cserélje le a teljes tartalmat main.cpp a következő kódra. Ez a kód a Windows-futtatókörnyezet API használatával próbálja lekérni az aktuális csomagidentitást. Ha sikerül, kinyomtatja a csomagcsalád nevét; ellenkező esetben a "Nincs csomagolva" felirat jelenik meg.

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

int main() {
    UINT32 length = 0;
    LONG result = GetCurrentPackageFamilyName(&length, nullptr);
    
    if (result == ERROR_INSUFFICIENT_BUFFER) {
        // We have a package identity
        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 {
        // No package identity
        std::cout << "Not packaged" << std::endl;
    }

    return 0;
}

3. Futtatás identitás nélkül

Most újraépítse és futtassa az alkalmazást a szokásos módon:

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

A "Nincs csomagolva" kimenetnek kell megjelennie. Ez megerősíti, hogy a standard végrehajtható fájl csomagidentitás nélkül fut.

4. A Project inicializálása winapp parancssori felülettel

A winapp init parancs minden szükséges elemet beállít egy lépésben: alkalmazásjegyzéket, objektumokat és opcionálisan Windows App SDK fejléceket a C++ fejlesztéshez.

Futtassa a következő parancsot, és kövesse az utasításokat:

winapp init .

Amikor a rendszer kéri:

  • Csomag neve: Nyomja le az Enter billentyűt az alapértelmezett (cpp-app) elfogadásához
  • Publisher név: Az Enter billentyűt lenyomva fogadja el az alapértelmezett értéket, vagy adja meg a nevét
  • Verzió: Nyomja le az Enter billentyűt az 1.0.0.0 elfogadásához
  • Belépési pont: Nyomja le az Enter billentyűt az alapértelmezett (cpp-app.exe) elfogadásához
  • Setup SDK-k: Válassza a "Stabil SDK-k" lehetőséget a Windows App SDK letöltéséhez és C++ fejlécek létrehozásához

Ez a parancs a következő lesz:

  • Létrehozza Package.appxmanifest – az alkalmazás identitását meghatározó jegyzék
  • Mappa létrehozása Assets – az MSIX-csomagoláshoz és az Áruház beküldéséhez szükséges ikonok
  • .winapp mappa létrehozása Windows App SDK fejlécekkel és kódtárakkal
  • winapp.yaml Konfigurációs fájl létrehozása SDK-verziók rögzítéséhez

Megnyithatja Package.appxmanifest az olyan tulajdonságok további testreszabásához, mint a megjelenítendő név, a közzétevő és a képességek.

Végrehajtási alias hozzáadása (konzolalkalmazásokhoz)

A végrehajtási alias lehetővé teszi, hogy a felhasználók név alapján futtatják az alkalmazást bármely terminálból (például cpp-app). A fejlesztés során is lehetővé teszi winapp run --with-alias , hogy a konzol kimenete az aktuális terminálban legyen új ablak megnyitása helyett.

Automatikusan hozzáadhat egyet:

winapp manifest add-alias

Vagy manuálisan: nyissa meg a Package.appxmanifest, és adja hozzá a uap5 névteret a <Package> címkéhez, ha hiányzik, majd illessze be a kiterjesztést a <Applications><Application><Extensions>... belsejébe.

<Package
  ...
  xmlns:uap10="http://schemas.microsoft.com/appx/manifest/uap/windows10/10"
+ xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5"
  IgnorableNamespaces="uap uap2 uap3 rescap desktop desktop6 uap10">

  ...
  <Applications>
    <Application ...>
      ...
+     <Extensions>
+       <uap5:Extension Category="windows.appExecutionAlias">
+         <uap5:AppExecutionAlias>
+           <uap5:ExecutionAlias Alias="cpp-app.exe" />
+         </uap5:AppExecutionAlias>
+       </uap5:Extension>
+     </Extensions>
    </Application>
  </Applications>
</Package>

5. Hibakeresés identitással

Az olyan funkciók teszteléséhez, amelyek identitást igényelnek (mint például az értesítések), az alkalmazás teljes csomagolása nélkül használhatja a winapp run eszközt. Ez regisztrál egy laza elrendezési csomagot (csakúgy, mint egy valódi MSIX-telepítés), és egy lépésben elindítja az alkalmazást. A hibakereséshez nincs szükség tanúsítványra vagy aláírásra.

  1. A végrehajtható fájl létrehozása:

    cmake --build build --config Debug
    
  2. Futtatás identitással:

    winapp run .\build\Debug --with-alias
    

A --with-alias jelző a végrehajtási aliasán keresztül indítja el az alkalmazást, így a konzol kimenete az aktuális terminálban marad. Ehhez szükség van a uap5:ExecutionAlias-re, amit a 4. lépésben adtunk hozzá.

Jótanács

winapp run a csomagot a rendszeren is regisztrálja. Ezért előfordulhat, hogy az MSIX "már telepítve" állapotban jelenik meg, amikor a 8. lépés későbbi részében megpróbálja telepíteni. A fejlesztési csomagok megtisztítására használható winapp unregister , ha elkészült.

Most a következőhöz hasonló kimenetnek kell megjelennie:

Package Family Name: cpp-app_12345abcde

Ez megerősíti, hogy az alkalmazás érvényes csomagazonosítóval fut!

Alternatíva: Ritka csomag azonosítója

Ha kifejezetten a csomag ritkán használt viselkedésére van szüksége (fájlok másolása nélküli identitásra), a következőt használhatja create-debug-identity :

winapp create-debug-identity .\build\Debug\cpp-app.exe
.\build\Debug\cpp-app.exe

Jótanács

A speciális hibakeresési munkafolyamatokat (hibakeresők csatolása, IDE-beállítás, indítási hibakeresés) a hibakeresési útmutatóban találja.

6. A Windows App SDK használata (nem kötelező)

Ha a winapp init során az SDK-k beállítását választotta, most már hozzáférhet Windows App SDK fejlécekhez a .winapp/include mappában. Ez hozzáférést biztosít a modern Windows API-khoz, például értesítésekhez, ablakozáshoz, eszközalapú AI-hoz és egyebekhez. Ha csak csomagidentitásra van szüksége a terjesztéshez, ugorjon a 7. lépésre.

Vegyünk fel egy egyszerű példát, amely kinyomtatja a Windows-alkalmazás futtatókörnyezet verzióját.

CMakeLists.txt frissítése

Adja hozzá a következő sort a CMakeLists.txt végéhez a Windows App SDK fejlécek belefoglalásához:

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

Main.cpp frissítése

Cserélje le a main.cpp teljes tartalmát a Windows-alkalmazás Runtime API használatára:

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

int main() {
    // Initialize WinRT
    winrt::init_apartment();
    
    UINT32 length = 0;
    LONG result = GetCurrentPackageFamilyName(&length, nullptr);
    
    if (result == ERROR_INSUFFICIENT_BUFFER) {
        // We have a package identity
        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;
            
            // Get Windows App Runtime version using the API
            auto runtimeVersion = winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::RuntimeInfo::AsString();
            std::wcout << L"Windows App Runtime Version: " << runtimeVersion.c_str() << std::endl;
        } else {
            std::wcout << L"Error retrieving Package Family Name" << std::endl;
        }
    } else {
        std::cout << "Not packaged" << std::endl;
    }
    
    return 0;
}

Építés és futtatás

Az alkalmazás újraépítése a Windows App SDK fejlécekkel:

cmake --build build --config Debug
winapp run .\build\Debug --with-alias

Most a következő kimenetnek kell megjelennie:

Package Family Name: cpp-app_12345abcde
Windows App Runtime Version: 1.8-stable (1.8.0)

A .winapp/include könyvtár tartalmazza a Windows App SDK összes szükséges fejlécét, beleértve a következőket:

  • winrt/ – WinRT C++ kivetítési fejlécek Windows-futtatókörnyezet API-k eléréséhez
  • Microsoft.UI.*.h – WinUI 3 fejlécek modern felhasználói felületi összetevőkhöz
  • MddBootstrap.h – Windows App SDK rendszerindítás
  • WindowsAppSDK-VersionInfo.h – Verzióadatok
  • És még sok más Windows App SDK összetevő

A fejlettebb Windows App SDK használatért tekintse meg a Windows App SDK dokumentációját.

7. Szükség esetén állítsa vissza a fejléceket

A .winapp mappa automatikusan hozzáadódik a .gitignore-hoz a winapp init által, ezért nem lesz beillesztve a forrásvezérlésbe. Amikor mások klónozzák a projektet, az építkezés előtt vissza kell állítaniuk ezeket a fájlokat.

Manuális beállítás

Futtassa ezt a két parancsot az adattár klónozása után:

# Restore Windows App SDK headers
winapp restore

# Generate development certificate (optional - only if planning to package the app and sideload)
winapp cert generate --if-exists skip

Ezután a cmake -B build és a cmake --build build --config Debug segítségével normál módon létrehozhatja és futtathatja.

Automatikus beállítás CMake-sel

Ezt úgy is automatizálhatja, hogy hozzáadja a beállítási logikát a sajátjához CMakeLists.txt. Itt van a teljes CMakeLists.txt, amely tartalmazza az automatizálást, a megfelelő összekapcsolást, és a C++20 szabvány minimális követelményeit:

cmake_minimum_required(VERSION 3.20)
project(cpp-app)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Download winapp CLI if not available in PATH
find_program(WINAPP_CLI winapp)
if(NOT WINAPP_CLI)
    set(WINAPP_DIR "${CMAKE_CURRENT_SOURCE_DIR}/.winapp-tools")
    set(WINAPP_CLI "${WINAPP_DIR}/winapp.exe")
    
    if(NOT EXISTS "${WINAPP_CLI}")
        message(STATUS "Downloading winapp CLI...")
        
        # Determine architecture
        if(CMAKE_SYSTEM_PROCESSOR MATCHES "ARM64|aarch64")
            set(WINAPP_ARCH "arm64")
        else()
            set(WINAPP_ARCH "x64")
        endif()
        
        # Download and extract
        set(WINAPP_ZIP "${CMAKE_CURRENT_BINARY_DIR}/winappcli.zip")
        file(DOWNLOAD 
            "https://github.com/microsoft/WinAppCli/releases/latest/download/winappcli-${WINAPP_ARCH}.zip"
            "${WINAPP_ZIP}"
            SHOW_PROGRESS
        )
        
        file(ARCHIVE_EXTRACT INPUT "${WINAPP_ZIP}" DESTINATION "${WINAPP_DIR}")
        file(REMOVE "${WINAPP_ZIP}")
        message(STATUS "winapp CLI downloaded to ${WINAPP_DIR}")
    endif()
endif()

# Automatically restore Windows App SDK headers and generate certificate if needed
# This runs once during CMake configuration, not on every build
if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.winapp/include")
    message(STATUS "Restoring Windows App SDK headers...")
    execute_process(
        COMMAND "${WINAPP_CLI}" restore
        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
        RESULT_VARIABLE RESTORE_RESULT
    )
    if(NOT RESTORE_RESULT EQUAL 0)
        message(WARNING "Failed to restore Windows App SDK. Run 'winapp restore' manually.")
    endif()
endif()

if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/devcert.pfx")
    message(STATUS "Generating development certificate...")
    execute_process(
        COMMAND "${WINAPP_CLI}" cert generate --if-exists skip
        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
        RESULT_VARIABLE CERT_RESULT
    )
    if(NOT CERT_RESULT EQUAL 0)
        message(WARNING "Failed to generate certificate. Run 'winapp cert generate' manually.")
    endif()
endif()

add_executable(cpp-app main.cpp)

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

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

Ezzel a beállítással:

  • Amikor valaki klónozza az adattárat, és fut cmake -B build, a rendszer automatikusan letölti a winappot, ha nem található a PATH-ban
  • A Windows App SDK fejlécek és tanúsítványok automatikusan visszaállnak
  • A parancsok csak egyszer futnak a konfiguráció során (nem minden builden), mert ellenőrzik, hogy a fájlok már léteznek-e
  • Ha a parancsok sikertelenek, a CMake figyelmeztetést jelenít meg a manuális futtatásra vonatkozó utasításokkal
  • A letöltött winapp tárolása itt történik: .winapp-tools/ (adja hozzá .gitignore-hez, ha szükséges)

8. Csomagolás MSIX-szel

Miután készen áll az alkalmazás terjesztésére, ugyanazzal a jegyzékfájllal MSIX-ként csomagolhatja be. Az MSIX tiszta telepítést/eltávolítást, automatikus frissítéseket és megbízható telepítési élményt biztosít.

A csomagkönyvtár előkészítése

Először hozza létre az alkalmazást kiadási módban az optimális teljesítmény érdekében:

cmake --build build --config Release

Ezután hozzon létre egy könyvtárat, amely csak a terjesztéshez szükséges fájlokat tartalmazza, és másolja a végrehajtható kiadást:

mkdir dist
copy .\build\Release\cpp-app.exe .\dist\

Fejlesztési tanúsítvány létrehozása

Az MSIX-csomagokat alá kell írni. Helyi teszteléshez hozzon létre egy önaláírt fejlesztési tanúsítványt:

winapp cert generate --if-exists skip

Jótanács

A tanúsítvány kiadójának meg kell egyeznie a Publisher-vel a Package.appxmanifest-ben. A cert generate parancs ezt automatikusan felolvassa a jegyzékből.

Aláírás és csomagolás

Most már csomagolhatja és aláírhatja a következőt:

# package and sign the app with the generated certificate
winapp pack .\dist --cert .\devcert.pfx 

Jótanács

A pack parancs automatikusan a Package.appxmanifest fájlt használja az aktuális könyvtárból, és a csomagolás előtt átmásolja a célmappába. A létrehozott .msix fájl az aktuális könyvtárban lesz.

A tanúsítvány telepítése

Az MSIX-csomag telepítése előtt meg kell bíznia a fejlesztési tanúsítványban a számítógépen. Futtassa ezt a parancsot rendszergazdaként (ezt tanúsítványonként csak egyszer kell elvégeznie):

winapp cert install .\devcert.pfx

Telepítés és futtatás

Jótanács

Ha az 5. lépésben használta winapp run , előfordulhat, hogy a csomag már regisztrálva van a rendszeren. Először winapp unregister távolítsa el a fejlesztési regisztrációt, majd telepítse a kiadási csomagot.

A winapp pack parancs létrehozza az MSIX-fájlt a projekt gyökérkönyvtárában. Telepítse a csomagot a létrehozott .msix fájlra duplán kattintva vagy a PowerShell használatával:

Add-AppxPackage .\cpp-app_1.0.0.0_x64.msix

Jótanács

Az MSIX fájlnév tartalmazza a verziót és az architektúrát (pl. cpp-app_1.0.0.0_arm64.msix). Ellenőrizze a könyvtárban a pontos fájlnevet.

Mostantól a terminál bármely pontjáról futtathatja az alkalmazást a következő beírással:

cpp-app

Látnia kell a "Csomagcsalád neve" kimenetet, amely megerősíti, hogy telepítve van, és identitással fut.

Jótanács

Ha újra kell csomagolnia az alkalmazást (például a kódmódosítások után), növelje a verziószámot a VersionPackage.appxmanifest futtatása előtt. Windows egy telepített csomag frissítéséhez magasabb verziószám szükséges.

Tips

  1. Miután készen áll a terjesztésre, aláírhatja az MSIX-et egy hitelesítésszolgáltató kódaláíró tanúsítványával, hogy a felhasználóknak ne kelljen önaláírt tanúsítványt telepíteniük.
  2. A Megbízható Azure-aláírás szolgáltatással biztonságosan kezelheti tanúsítványait, és integrálhatja a CI/CD-folyamatba való bejelentkezést.
  3. A Microsoft Store aláírja Önnek az MSIX-et, a beküldés előtt nem kell aláírnia.
  4. Előfordulhat, hogy több MSIX-csomagot kell létrehoznia, egyet minden támogatott architektúrához (x64, Arm64). Konfigurálja a CMake-t a megfelelő generátor- és architektúrajelzőkkel.

Következő lépések