Używanie narzędzia winapp CLI z językiem C++ i systemem budowania CMake.

W tym przewodniku pokazano, jak używać interfejsu winapp wiersza polecenia z aplikacją języka C++ do debugowania przy użyciu tożsamości pakietu i spakowania aplikacji jako pliku MSIX.

Tożsamość pakietu jest podstawową koncepcją w modelu Windows app. Umożliwia Twojej aplikacji dostęp do specyficznych interfejsów API Windows (takich jak powiadomienia, zabezpieczenia, interfejsy API sztucznej inteligencji itp.), zapewnia czyste środowisko instalacji i dezinstalacji oraz oferuje wiele innych funkcji.

Standardowy plik wykonywalny (taki jak utworzony za pomocą cmake --buildpolecenia ) nie ma tożsamości pakietu. W tym przewodniku pokazano, jak dodać go do debugowania, a następnie spakować go do dystrybucji.

Wymagania wstępne

  1. Narzędzia kompilacji: użyj łańcucha narzędzi kompilatora obsługiwanego przez narzędzie CMake. W tym przykładzie użyto Visual Studio. Możesz zainstalować edycję społecznościową za pomocą (lub zaktualizować, jeśli jest już zainstalowana):

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

    Uruchom ponownie po instalacji.

  2. CMake: Zainstaluj narzędzie CMake (lub zaktualizuj, jeśli jest już zainstalowane):

    winget install Kitware.CMake --source winget
    
  3. winapp CLI: zainstaluj winapp CLI za pomocą winget (lub zaktualizuj, jeśli jest już zainstalowany):

    winget install Microsoft.winappcli --source winget
    

1. Tworzenie nowej aplikacji języka C++

Zacznij od utworzenia prostej aplikacji języka C++. Utwórz nowy katalog dla projektu.

mkdir cpp-app
cd cpp-app

main.cpp Utwórz plik z podstawowym programem "Hello, world!":

#include <iostream>

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

CMakeLists.txt Utwórz plik w celu skonfigurowania kompilacji:

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)

Skompiluj i uruchom go, aby upewnić się, że wszystko działa:

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

Dane wyjściowe powinny mieć wartość "Hello, world!"

2. Zaktualizuj kod, aby sprawdzić tożsamość

Zaktualizujemy aplikację, aby sprawdzić, czy jest ona uruchomiona przy użyciu tożsamości pakietu. Pomoże nam to sprawdzić, czy tożsamość działa poprawnie w kolejnych krokach. Użyjemy interfejsu API środowisko wykonawcze systemu Windows w języku C++ aby uzyskać dostęp do interfejsów API pakietów.

Najpierw dodaj następujący wiersz na końcu CMakeLists.txt, aby połączyć się z biblioteką aplikacja dla systemu Windows Model:

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

Następnie zastąp całą zawartość main.cpp następującym kodem. Ten kod próbuje pobrać bieżącą tożsamość pakietu przy użyciu interfejsu API środowisko wykonawcze systemu Windows. Jeśli to się powiedzie, wyświetla nazwę rodziny pakietów; w przeciwnym razie wyświetla tekst "Nie spakowane".

#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. Uruchamianie bez tożsamości

Teraz odbuduj i uruchom aplikację jak zwykle.

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

Powinny zostać wyświetlone dane wyjściowe "Nie spakowane". Potwierdza to, że standardowy plik wykonywalny jest uruchomiony bez żadnej tożsamości pakietu.

4. Inicjowanie Projektu za pomocą CLI winapp

Polecenie winapp init konfiguruje wszystko, czego potrzebujesz w jednym miejscu: manifest aplikacji, zasoby i opcjonalnie nagłówki Zestaw SDK do aplikacji systemu Windows na potrzeby programowania w języku C++.

Uruchom następujące polecenie i postępuj zgodnie z monitami:

winapp init .

Po wyświetleniu monitu:

  • Nazwa pakietu: naciśnij klawisz Enter, aby zaakceptować wartość domyślną (cpp-app)
  • Nazwa wydawcy: Naciśnij klawisz Enter, aby zaakceptować wartość domyślną lub wprowadź swoją nazwę
  • Wersja: Naciśnij klawisz Enter, aby zaakceptować 1.0.0.0
  • Punkt wejścia: Naciśnij klawisz Enter, aby zaakceptować wartość domyślną (cpp-app.exe)
  • Setup SDK: Wybierz pozycję "Stabilne zestawy SDK", aby pobrać Zestaw SDK do aplikacji systemu Windows i wygenerować nagłówki języka C++

To polecenie spowoduje:

  • Utwórz Package.appxmanifest — manifest, który definiuje tożsamość aplikacji
  • Utwórz folder Assets — ikony wymagane do tworzenia pakietów MSIX i wysyłania do Sklepu
  • Tworzenie folderu .winapp z nagłówkami i bibliotekami Zestaw SDK do aplikacji systemu Windows
  • Utwórz plik konfiguracji winapp.yaml dla przypisania wersji SDK

Możesz otworzyć Package.appxmanifest aby jeszcze bardziej dostosować właściwości, takie jak nazwa wyświetlana, wydawca i funkcje.

Dodawanie aliasu wykonywania (dla aplikacji konsolowych)

Alias wykonywania umożliwia użytkownikom uruchamianie aplikacji według nazwy z dowolnego terminalu (na przykład cpp-app). Włącza również winapp run --with-alias podczas programowania, co powoduje zachowanie danych wyjściowych konsoli w bieżącym terminalu zamiast otwierania nowego okna.

Możesz dodać jeden automatycznie:

winapp manifest add-alias

Lub ręcznie: otwórz Package.appxmanifest i dodaj przestrzeń nazw uap5 do tagu <Package>, jeśli brakuje, a następnie dodaj rozszerzenie wewnątrz <Applications><Application><Extensions>...:

<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. Debugowanie przy użyciu tożsamości

Aby przetestować funkcje wymagające tożsamości (takich jak powiadomienia) bez pełnego pakowania aplikacji, możesz użyć polecenia winapp run. Spowoduje to zarejestrowanie luźnego pakietu układu (podobnie jak prawdziwa instalacja MSIX) i uruchomienie aplikacji w jednym kroku. Do debugowania nie jest wymagany żaden certyfikat ani podpisywanie.

  1. Skompiluj plik wykonywalny:

    cmake --build build --config Debug
    
  2. Uruchom z tożsamością:

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

Flaga --with-alias uruchamia aplikację za pomocą aliasu wykonawczego, dzięki czemu dane wyjściowe konsoli pozostają w bieżącym terminalu. Wymaga to dodania uap5:ExecutionAlias w kroku 4.

Wskazówka

winapp run rejestruje również pakiet w systemie. Dlatego plik MSIX może być wyświetlany jako "już zainstalowany" podczas próby zainstalowania go w dalszej części kroku 8. Użyj winapp unregister, aby wyczyścić pakiety programistyczne po zakończeniu pracy.

Powinny zostać wyświetlone dane wyjściowe podobne do następujących:

Package Family Name: cpp-app_12345abcde

Potwierdza to, że aplikacja jest uruchomiona z prawidłową tożsamością pakietu!

Alternatywna: tożsamość pakietu rozrzednego

Jeśli potrzebujesz zachowania rozrzedzeni pakietu w szczególności (tożsamość bez kopiowania plików), możesz użyć zamiast tego create-debug-identity :

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

Wskazówka

Aby uzyskać zaawansowane scenariusze debugowania (dołączanie debugerów, konfigurowanie środowiska IDE, debugowanie uruchamiania), zobacz Przewodnik debugowania.

6. Używanie Zestaw SDK do aplikacji systemu Windows (opcjonalnie)

Jeśli wybrano opcję konfigurowania zestawów SDK podczas winapp init, masz teraz dostęp do nagłówków Zestaw SDK do aplikacji systemu Windows w folderze .winapp/include. Zapewnia to dostęp do nowoczesnych interfejsów API Windows, takich jak powiadomienia, okna, sztuczna inteligencja na urządzeniu i inne. Jeśli potrzebujesz tożsamości pakietu do dystrybucji, możesz przejść do kroku 7.

Dodajmy prosty przykład, który wyświetla wersję aplikacja dla systemu Windows Runtime.

Zaktualizuj CMakeLists.txt

Dodaj następujący wiersz na końcu CMakeLists.txt, aby uwzględnić nagłówki Zestaw SDK do aplikacji systemu Windows:

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

Aktualizowanie main.cpp

Zastąp całą zawartość main.cpp, aby użyć interfejsu API aplikacja dla systemu Windows Runtime.

#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;
}

Budowanie i uruchamianie

Odbuduj aplikację z użyciem nagłówków Zestaw SDK do aplikacji systemu Windows:

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

Powinny zostać wyświetlone dane wyjściowe, takie jak:

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

Katalog .winapp/include zawiera wszystkie niezbędne nagłówki dla Zestaw SDK do aplikacji systemu Windows, w tym:

  • winrt/ — nagłówki projekcji WinRT C++ na potrzeby uzyskiwania dostępu do interfejsów API środowisko wykonawcze systemu Windows
  • Microsoft.UI.*.h — nagłówki WinUI 3 dla nowoczesnych składników interfejsu użytkownika
  • MddBootstrap.h – Uruchamianie Zestaw SDK do aplikacji systemu Windows
  • WindowsAppSDK-VersionInfo.h - Informacje o wersji
  • I wiele innych składników Zestaw SDK do aplikacji systemu Windows

Aby uzyskać bardziej zaawansowane użycie Zestaw SDK do aplikacji systemu Windows, zapoznaj się z dokumentacją Zestaw SDK do aplikacji systemu Windows.

7. Przywróć nagłówki w razie potrzeby

Folder .winapp jest automatycznie dodawany do .gitignore przez winapp init program, więc nie zostanie dodany do kontroli wersji. Gdy inne osoby sklonują Twój projekt, będą musiały przywrócić te pliki przed kompilacją.

Konfiguracja ręczna

Uruchom następujące dwa polecenia po sklonowaniu repozytorium:

# 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

Następnie możesz skompilować i uruchomić normalnie za pomocą polecenia cmake -B build i cmake --build build --config Debug.

Automatyczna instalacja za pomocą narzędzia CMake

Alternatywnie możesz to zautomatyzować, dodając logikę konfiguracji do elementu CMakeLists.txt. Oto pełny CMakeLists.txt z automatyzacją, prawidłowym łączeniem i minimalnym wykorzystaniem standardu C++20:

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)

W przypadku tej konfiguracji:

  • Gdy ktoś sklonuje repozytorium i uruchomi cmake -B buildpolecenie , aplikacja winapp zostanie automatycznie pobrana, jeśli nie zostanie znaleziona w ścieżce PATH
  • Nagłówki i certyfikaty Zestaw SDK do aplikacji systemu Windows są automatycznie przywracane
  • Polecenia są uruchamiane tylko raz podczas konfiguracji (nie w każdej kompilacji), ponieważ sprawdzają, czy pliki już istnieją
  • Jeśli polecenia kończą się niepowodzeniem, narzędzie CMake wyświetla ostrzeżenie z instrukcjami dotyczącymi ręcznego uruchamiania
  • Pobrana aplikacja winapp jest przechowywana w pliku .winapp-tools/ (dodaj tę aplikację w .gitignore razie potrzeby)

8. Pakiet z plikiem MSIX

Gdy wszystko będzie gotowe do dystrybucji aplikacji, możesz spakować ją jako plik MSIX przy użyciu tego samego manifestu. MsiX zapewnia czystą instalację/odinstalowywanie, automatyczne aktualizacje i zaufane środowisko instalacji.

Przygotowywanie katalogu pakietów

Najpierw skompiluj aplikację w trybie wydania, aby uzyskać optymalną wydajność:

cmake --build build --config Release

Następnie utwórz katalog zawierający tylko pliki potrzebne do dystrybucji i skopiuj plik wykonywalny wydania:

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

Generowanie certyfikatu programistycznego

Pakiety MSIX muszą być podpisane. Na potrzeby testowania lokalnego wygeneruj certyfikat programowania z podpisem własnym:

winapp cert generate --if-exists skip

Wskazówka

Wydawca certyfikatu musi być zgodny z Publisher w Package.appxmanifest. Polecenie cert generate odczytuje to automatycznie z manifestu.

Podpisywanie i pakowanie

Teraz możesz spakować i podpisać:

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

Wskazówka

Polecenie pack automatycznie używa pliku Package.appxmanifest z bieżącego katalogu i kopiuje go do folderu docelowego przed opakowaniem. Wygenerowany .msix plik będzie znajdować się w bieżącym katalogu.

Instalowanie certyfikatu

Przed zainstalowaniem pakietu MSIX należy ufać certyfikatowi programistycznemu na maszynie. Uruchom to polecenie jako administrator (wystarczy to zrobić tylko raz na certyfikat):

winapp cert install .\devcert.pfx

Instalowanie i uruchamianie

Wskazówka

Jeśli użyto winapp run w kroku 5, pakiet może być już zarejestrowany w systemie. Najpierw usuń rejestrację deweloperską winapp unregister, a następnie zainstaluj pakiet produkcyjny.

Polecenie winapp pack generuje plik MSIX w katalogu głównym projektu. Zainstaluj pakiet, klikając dwukrotnie wygenerowany .msix plik lub przy użyciu programu PowerShell:

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

Wskazówka

Nazwa pliku MSIX zawiera wersję i architekturę (np. cpp-app_1.0.0.0_arm64.msix). Sprawdź katalog pod kątem dokładnej nazwy pliku.

Teraz możesz uruchomić aplikację z dowolnego miejsca w terminalu, wpisując:

cpp-app

Powinny zostać wyświetlone dane wyjściowe "Nazwa rodziny pakietów", potwierdzające, że pakiet został zainstalowany i działa z unikalnym identyfikatorem.

Wskazówka

Jeśli musisz ponownie spakować aplikację (np. po zmianie kodu), zwiększ Version wartość w Package.appxmanifest przed ponownym uruchomieniem winapp pack . Windows wymaga wyższego numeru wersji w celu zaktualizowania zainstalowanego pakietu.

Porady

  1. Gdy wszystko będzie gotowe do dystrybucji, możesz podpisać plik MSIX przy użyciu certyfikatu podpisywania kodu z urzędu certyfikacji, aby użytkownicy nie musieli instalować certyfikatu z podpisem własnym.
  2. Usługa Azure Trusted Signing to doskonały sposób na bezpieczne zarządzanie certyfikatami i integrację podpisywania z potokiem ciągłej integracji i ciągłego wdrażania.
  3. Microsoft Store podpisze plik MSIX bez konieczności podpisywania przed przesłaniem.
  4. Może być konieczne utworzenie wielu pakietów MSIX — po jednym dla każdej obsługiwanej architektury (x64, Arm64). Skonfiguruj narzędzie CMake przy użyciu odpowiednich flag generatora i architektury.

Dalsze kroki