通过


将 winapp CLI 与 C++ 和 CMake 配合使用

本指南演示如何将 winapp CLI 与 C++ 应用程序配合使用,以包标识进行调试,并将应用程序打包为 MSIX。

包标识是Windows app模型中的核心概念。 它允许应用程序access特定的 Windows API(例如通知、安全、AI API 等),具有全新安装/卸载体验等。

标准可执行文件(如使用 cmake --build创建的可执行文件)没有包标识。 本指南演示如何添加它进行调试,然后将其打包以供分发。

先决条件

  1. 生成工具:使用 CMake 支持的编译器工具链。 此示例使用Visual Studio。 可以使用以下功能安装社区版:

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

    安装后重新启动。

  2. CMake:安装 CMake:

    winget install Kitware.CMake --source winget
    
  3. winapp CLI:通过 winget 安装 winapp CLI:

    winget install Microsoft.winappcli --source winget
    

1.创建新的 C++ 应用

首先创建简单的 C++ 应用程序。 为您的项目创建新目录。

mkdir cpp-app
cd cpp-app

创建一个包含基本“Hello, world!”程序的main.cpp文件:

#include <iostream>

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

创建一个CMakeLists.txt 文件以配置构建:

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)

生成并运行它以确保一切正常工作:

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

2.更新代码以检查标识

更新应用程序,使用 Windows Runtime C++ API 检查是否以包标识运行。

首先,更新 CMakeLists.txt 以链接到 Windows App 模型库:

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)

接下来,替换 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.在没有标识的情况下运行

重新生成并运行应用:

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

您应能看到“未打包”。 这确认标准可执行文件在没有任何包标识的情况下正在运行。

4. 使用 winapp CLI 初始化项目

winapp init 命令设置所需的一切:应用清单、资产和(可选)用于 C++ 开发的Windows App SDK标头。

winapp init

出现提示时:

  • 程序包名称:按 Enter 接受默认 (cpp-app)
  • 发布者名称:按 Enter 接受默认值或输入名称
  • 版本:按 Enter 接受 1.0.0.0
  • 入口点:按 Enter 接受默认值(cpp-app.exe)
  • Setup SDK:选择“稳定 SDK”以下载Windows App SDK并生成标头

此命令创建:

  • appxmanifest.xmlAssets 文件夹用于应用程序标识
  • 具有Windows App SDK标头和库的 .winapp 文件夹
  • winapp.yaml用于固定 SDK 版本的配置文件

5. 使用身份进行调试

若要在不完全打包应用的情况下测试需要身份验证的功能,请使用 winapp create-debug-identity

  1. 生成可执行文件

    cmake --build build --config Debug
    
  2. 应用调试标识

    winapp create-debug-identity .\build\Debug\cpp-app.exe
    
  3. 运行可执行文件

    .\build\Debug\cpp-app.exe
    

现在应会看到类似于以下内容的输出:

Package Family Name: cpp-app_12345abcde

自动化调试身份(可选)

CMakeLists.txt中添加一个生成后命令,以自动应用调试身份:

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. 使用 Windows App SDK (可选)

如果您选择在 winapp init 时设置 SDK,您可以在 .winapp/include 文件夹中访问 Windows App SDK 标头。

更新CMakeLists.txt以包含标题:

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

更新 main.cpp 以使用 Windows App 运行时环境 API。

#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. 根据需要还原标头

文件夹 .winapp 会自动添加到 .gitignore。 当其他人克隆你的项目时,他们需要还原这些文件:

winapp restore
winapp cert generate --if-exists skip

8. 使用 MSIX 打包

准备好分发后,打包为 MSIX:

  1. 准备发布

    cmake --build build --config Release
    
  2. 准备包目录

    mkdir dist
    copy .\build\Release\cpp-app.exe .\dist\
    
  3. 生成开发证书

    winapp cert generate --if-exists skip
    
  4. 打包和签名

    winapp pack .\dist --cert .\devcert.pfx
    
  5. 安装证书 (以管理员身份运行):

    winapp cert install .\devcert.pfx
    
  6. 安装和运行

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

小窍门

  • 使用证书颁发机构的代码签名证书对 MSIX 进行签名,以便进行生产分发。
  • 微软商店为你签署MSIX,无需在提交之前签署。
  • 对于支持的每个体系结构,可能需要单独的 MSIX 包(x64,Arm64)。