Использование интерфейса командной строки winapp с .NET

Это руководство должно работать для большинства типов проектов .NET. Шаги были протестированы с помощью консольных и пользовательских проектов, таких как WPF. Примеры работы см. в примерах dotnet-app (консоль) и wpf-app (WPF) в папке примеров.

В этом руководстве показано, как использовать интерфейс командной строки winapp с приложением .NET для отладки с помощью удостоверения пакета и упаковки приложения в виде MSIX.

Идентификатор пакета — это основная концепция модели приложений Windows. Это позволяет приложению получать доступ к определенным API-интерфейсам Windows (например, уведомлениям, безопасности, API ИИ и т. д.), иметь чистый интерфейс установки и удаления и многое другое.

Стандартный исполняемый файл (например, созданный с dotnet build) не имеет удостоверения пакета. В этом руководстве показано, как добавить его для отладки, а затем упаковать его для распространения.

Необходимые условия

  1. пакет SDK .NET: установите пакет SDK .NET (требуется перезапуск после установки):

    winget install Microsoft.DotNet.SDK.10 --source winget
    
  2. winapp CLI: установите winapp средство с помощью winget (или обновите, если оно уже установлено):

    winget install Microsoft.winappcli --source winget
    

1. Создание нового приложения .NET

Начните с создания простого консольного приложения .NET:

dotnet new console -n dotnet-app
cd dotnet-app

Запустите его, чтобы убедиться, что все работает:

dotnet run

Выходные данные должны быть "Hello, World!"

2. Обновление кода для проверки удостоверения

Мы обновим приложение, чтобы проверить, работает ли оно с идентификацией пакета. Мы будем использовать API среда выполнения Windows для доступа к API пакетов.

Сначала обновите файл project, чтобы выбрать определенную версию пакета SDK для Windows. Откройте dotnet-app.csproj и измените TargetFramework, чтобы включить версию пакета SDK Windows:

  <TargetFramework>net10.0-windows10.0.26100.0</TargetFramework>

Это дает доступ к среда выполнения Windows API без необходимости использования дополнительных пакетов.

Теперь замените содержимое Program.cs следующим кодом. Этот код пытается получить текущее удостоверение пакета с помощью API среда выполнения Windows. Если он успешно выполнен, он выводит имя семейства пакетов; в противном случае он выводит сообщение "Не упакованно".

using Windows.ApplicationModel;

try
{
    var package = Package.Current;
    var familyName = package.Id.FamilyName;
    Console.WriteLine($"Package Family Name: {familyName}");
}
catch (InvalidOperationException)
{
    // Thrown when app doesn't have package identity
    Console.WriteLine("Not packaged");
}

3. Запуск без идентификации

Теперь запустите приложение как обычно:

dotnet run

Вы должны увидеть сообщение "Не упаковано". Это подтверждает, что стандартный исполняемый файл выполняется без идентификатора пакета.

4. Инициализируйте проект с помощью winapp CLI

Команда winapp init автоматически обнаруживает файлы .csproj и запускает программу установки .NET. Он настраивает все, что вам нужно за один раз: проверяет ваши TargetFramework, добавляет необходимые пакеты NuGet, создает манифест приложения и ресурсы приложения.

Выполните следующую команду и следуйте подсказкам.

winapp init

Когда появится запрос:

  • Имя пакета: нажмите клавишу Enter, чтобы принять значение по умолчанию (dotnet-app)
  • Имя издателя: нажмите клавишу Enter, чтобы принять значение по умолчанию или введите своё имя.
  • Версия: нажмите клавишу ВВОД, чтобы принять 1.0.0.0
  • Description: нажмите Enter, чтобы принять описание по умолчанию (приложение Windows) или введите собственное описание.
  • настройка Windows App SDK: выбор стабильной, предварительной версии или экспериментальной версии (определяет, какая версия добавлена Windows App SDK)
  • TargetFramework update: если TargetFramework не содержит поддерживаемую версию пакета SDK Windows, вам будет предложено обновить его (например, net10.0-windows10.0.26100.0)
  • Режим разработчика: если появится запрос на "Режим разработчика", его можно включить, если вы хотите, но помните, что для него требуются права администратора.

Эта команда выполнит следующее действие:

  • Обновите TargetFramework в .csproj на поддерживаемый Windows TFM (при необходимости)
  • Добавьте Microsoft.WindowsAppSDK, Microsoft.Windows.SDK.BuildTools и Microsoft.Windows.SDK.BuildTools.WinApp ссылки на пакет NuGet в .csproj
  • Создайте папки Package.appxmanifest и Assets для удостоверения приложения

Замечание

В отличие от проектов на native/C++, поток .NET не создает файл winapp.yaml. Пакеты NuGet управляются непосредственно с помощью вашего .csprojприложения. После клонирования запустите winapp restore или dotnet restore.

Вы можете открыть Package.appxmanifest, чтобы дополнительно настроить такие свойства, как отображаемое имя, издатель и возможности.

Чтобы убедиться, что пакеты были добавлены в ваш проект:

dotnet list package

В выходных данных должны отображаться Microsoft.WindowsAppSDK и Microsoft.Windows.SDK.BuildTools.

Выходные данные консоли (ничего не нужно делать)

Так как мы создадим консольное приложение, выходные данные консоли должны оставаться в текущем терминале. Активация AUMID не даёт упакованному приложению доступа к консоли, поэтому консольное приложение будет работать корректно, но ничего не выведет.

winapp обрабатывает это за вас: вместо этого приложение с OutputType=Exe запускается через псевдоним выполнения, который наследует stdin/stdout/stderr вашего терминала. Он добавляет необходимый uap5:ExecutionAlias в подготавливаемый манифест, поэтому ничего настраивать не нужно.

Приложения пользовательского интерфейса (WPF, WinForms, WinUI) отображают собственное окно, поэтому они сохраняют активацию AUMID.

Чтобы всё же принудительно задать AUMID для консольного приложения, установите следующее внутри любого <PropertyGroup> в dotnet-app.csproj — тогда приложение будет запускаться без консоли и ничего не выводить в терминал:

<WinAppRunUseExecutionAlias>false</WinAppRunUseExecutionAlias>

Если вы предпочитаете выбрать имя команды самостоятельно, выполните winapp manifest add-alias, чтобы объявить его в Package.appxmanifest; созданный вами псевдоним будет использоваться как есть.

5. Отладка с помощью идентификации

Так как winapp init добавлен пакет NuGet Microsoft.Windows.SDK.BuildTools.WinApp в проект, можно просто запустить:

dotnet run

При этом автоматически вызывается winapp run под капотом — создание гибкого пакета макета, регистрация его в Windows и запуск приложения с полными правами пакета.

Аргументы, которые вы указываете после dotnet run, передаются в ваше приложение точно так же, как если бы проект не ссылался на этот пакет:

dotnet run --devtools          # your app receives --devtools
dotnet run -- --devtools       # identical: the SDK consumes the -- before forwarding

Используйте --, когда флаг вашего приложения также является параметром dotnet run (--configuration, --framework, --project, -c, -f, -r, ...) — без него SDK перехватывает токен, и ваше приложение никогда его не получает:

dotnet run -- --configuration Release   # your app receives --configuration Release

Настройте средство запуска WinApp с помощью WinAppRun* свойств MSBuild. MSBuild обрабатывает их сам, поэтому они никогда не доходят до вашего приложения:

dotnet run -p:WinAppRunDebugOutput=true --devtools

Здесь свойство настраивает WinApp, в то время как --devtools передаётся в ваше приложение. Полный список свойств, а также сведения о том, какие из них нельзя комбинировать, см. в dotnet runразделе поддержки.

Замечание

Вы можете увидеть предупреждения об уязвимостях NuGet (NU1900) о источниках пакетов. Это безопасно игнорировать. Они не влияют на сборочный процесс.

Выходные данные должны выглядеть примерно так:

Package Family Name: dotnet-app_12345abcde

Это подтверждает, что ваше приложение работает с действительным удостоверением пакета!

Альтернатива: вручную winapp run

Если вы не использовали winapp init (или удалили пакет NuGet), можно создать и запустить вручную. winapp run принимает проект напрямую (режим проекта) — он собирает .csproj и запускает его, поэтому вам не нужно отдельно указывать папку с результатами сборки или выполнять сборку:

# Build and run the project in one step (project mode)
winapp run .

# ...or run a specific project / configuration / architecture
winapp run .\dotnet-app.csproj -c Debug --arch x64

Чтобы запустить конфигурацию Native AOT проекта, включите AOT в проекте и выполните:

winapp run . --aot
winapp run . --aot -c Release

Используйте x64 или ARM64. Для однократного переопределения добавьте -p PublishAot=true.

Можно по-прежнему указывать winapp run на предварительно созданную папку вывода, если вы предпочитаете (режим папки):

dotnet build -c Debug
winapp run .\bin\Debug\net10.0-windows10.0.26100.0

Режим проекта поддерживает приложения WinUI в пакете и без пакета — он определяет нужный тип по файлу WindowsPackageType проекта и автоматически устанавливает приложение для Windows Runtime с соответствующей архитектурой. Чтобы принудительно запустить упакованный проект в незапакованном виде, добавьте -p WindowsPackageType=None.

Многопроектные приложения (приложение, ссылающееся на библиотеки классов) корректно собираются: winapp сохраняет ссылки AnyCPU/netstandard2.0 на их совместимой платформе вместо принудительного распространения архитектуры приложения на весь граф зависимостей. Только RID остается значением по умолчанию; Если для эффективной конфигурации требуется автономный профиль (например, обрезанный выпуск сборки), winapp выбирает соответствующий профиль, не изменяя платформы ссылочных библиотек.

Выходные потоки dotnet build отображаются в реальном времени, при этом сначала выводится точная команда вызова. Добавьте --verbose для трассировки принятия решений самой winapp о сборке. Требуется .NET пакет SDK 8.0.100 или более поздней версии. См. winapp runв справочнике по использованию полный список параметров.

Нет установленного пакета SDK Windows? Для создания проектов разработки C#/WinRT обычно требуется зарегистрированный пакет SDK Windows. Если режим проекта ничего не обнаруживает (в чистых CI-средах, контейнерах и на машинах разработчиков без SDK), он указывает cswinrt на файлы winmd из автоматически восстановленного пакета Microsoft.Windows.SDK.NET.Ref, чтобы сборка всё равно выполнялась успешно — никаких действий не требуется. Это не делает ничего, если установлен пакет SDK или когда вы устанавливаете -p CsWinRTWindowsMetadata=… самостоятельно.

Чтобы добавить пакет NuGet обратно: dotnet add package Microsoft.Windows.SDK.BuildTools.WinApp --prerelease

Подсказка

Чтобы отключить автоматическую dotnet run интеграцию, добавьте <EnableWinAppRunSupport>false</EnableWinAppRunSupport> в .csproj. Дополнительные сведения о параметрах настройки см. в документации по поддержке dotnet run .

Альтернатива: упрощённая идентификация пакета

Если вам нужен именно разреженный режим работы пакета (идентичность без копирования файлов), можно использовать create-debug-identity вместо этого. Это регистрирует разреженный пакет, указывающий на exe, а не создание свободного макета:

winapp create-debug-identity .\bin\Debug\net10.0-windows10.0.26100.0\dotnet-app.exe

Затем запустите исполняемый файл напрямую (не используйте dotnet run, так как он может перестроить или перезаписать файл):

.\bin\Debug\net10.0-windows10.0.26100.0\dotnet-app.exe

Альтернатива: целевой объект MSBuild вручную

Если вы предпочитаете не использовать пакет NuGet, можно добавить пользовательскую цель MSBuild, которая выполняется после отладочной сборки create-debug-identity. Добавьте это в файл .csproj в конце, непосредственно перед закрывающим тегом </Project>:

  <!-- Automatically apply debug identity after Debug builds -->
  <Target Name="ApplyDebugIdentity" AfterTargets="Build" Condition="'$(Configuration)' == 'Debug'">
    <Exec Command="winapp create-debug-identity &quot;$(TargetDir)$(TargetName).exe&quot;" 
          WorkingDirectory="$(ProjectDir)" 
          IgnoreExitCode="false" />
  </Target>

С помощью этой конфигурации dotnet build применяется идентификатор отладки, и вы можете запустить исполняемый файл напрямую. Обратите внимание, что dotnet run может привести к перестройке и перезаписи идентификатора, поэтому запустите exe вручную после сборки.

Подсказка

Дополнительные рабочие процессы отладки (присоединение отладчиков, настройка интегрированной среды разработки, отладка запуска) см. в руководстве по отладке.

Если вы предпочитаете явный контроль над применением идентификации или если вы пишете код, для которого идентификация не требуется на большинстве этапов разработки, то приведенный выше подход вручную тем может быть проще.

6. Использование Windows App SDK (необязательно)

Windows App SDK предоставляет доступ к современным API-интерфейсам Windows за пределами того, что предоставляет базовый пакет SDK для Windows , такие как система уведомлений, интерфейсы API окна, управление жизненным циклом приложений и ИИ на устройстве. Если ваше приложение нуждается в любой из этих возможностей, этот шаг предназначен для вас. Если вам просто нужен идентификатор пакета для распространения, можно перейти к шагу 7.

Если вы выполнили winapp init (шаг 4), Microsoft.WindowsAppSDK уже добавлен в качестве ссылки на пакет NuGet для .csproj. Вы можете проверить с помощью dotnet list package. Если вы пропустили программу установки пакета SDK во время инициализации или необходимо добавить ее вручную, выполните следующую команду:

dotnet add package Microsoft.WindowsAppSDK

Обновите Program.cs

Замените все содержимое Program.cs следующим кодом, который добавляет проверку версии среды выполнения приложение для Windows:

using Windows.ApplicationModel;

class Program
{
    static void Main(string[] args)
    {
        try
        {
            var package = Package.Current;
            var familyName = package.Id.FamilyName;
            Console.WriteLine($"Package Family Name: {familyName}");
            
            // Get Windows App Runtime version using the API
            var runtimeVersion = Microsoft.Windows.ApplicationModel.WindowsAppRuntime.RuntimeInfo.AsString;
            Console.WriteLine($"Windows App Runtime Version: {runtimeVersion}");
        }
        catch (InvalidOperationException)
        {
            // Thrown when app doesn't have package identity
            Console.WriteLine("Not packaged");
        }
    }
}

Сборка и запуск

Перестройте и запустите приложение с помощью Windows App SDK. Так как мы добавили WinAppSDK, необходимо повторно зарегистрироваться с идентификатором, чтобы winapp добавить зависимость среды выполнения. Если вы добавили пакет NuGet WinApp (рекомендуется), просто запустите dotnet run. В противном случае (замените dotnet-app на имя вашего проекта):

dotnet build -c Debug
winapp run .\bin\Debug\net10.0-windows10.0.26100.0

Теперь вы увидите такие выходные данные:

Package Family Name: dotnet-app.debug_12345abcde
Windows App Runtime Version: 8000.770.947.0

Пакет NuGet Windows App SDK включает все необходимые сборки для доступа к современным API Windows, включая:

  • Уведомления и активные плитки
  • Жизненный цикл окон и приложений
  • Push-уведомления
  • И многие другие Windows App SDK компоненты

Дополнительные сведения об использовании Windows App SDK см. в документации Windows App SDK.

7. Пакет с MSIX

Когда вы будете готовы к распространению приложения, его можно упаковать как MSIX с помощью того же манифеста.

Сборка для релиза

Сначала создайте приложение в режиме выпуска для оптимальной производительности:

dotnet build -c Release

Замечание

Вы можете увидеть предупреждения об уязвимостях NuGet (NU1900). Это можно безопасно игнорировать, они не влияют на данные выхода сборки.

Создание сертификата разработки

Перед упаковкой требуется сертификат разработчика для подписи. Создайте его, если вы еще не сделали:

winapp cert generate --if-exists skip

Подписание и упаковка

Теперь вы можете упаковывать и подписывать. Укажите команду пакета в выходную папку сборки (замените dotnet-app и путь TFM со значениями проекта):

# package and sign the app with the generated certificate
winapp pack .\bin\Release\net10.0-windows10.0.26100.0 --manifest .\Package.appxmanifest --cert .\devcert.pfx 

Примечание. Команда pack автоматически использует Package.appxmanifest из текущего каталога и копирует ее в целевую папку перед упаковкой. Созданный MSIX-файл будет находиться в текущем каталоге.

Совет. Вы также можете пропустить поиск папки выходных данных сборки и пакета прямо из проекта— winapp package .\dotnet-app.csproj --cert .\devcert.pfx публикует проект и упаковывает его выходные данные на одном шаге (режим проекта по умолчанию используется для конфигурации выпуска). Режим проекта принимает параметры сборки -c, --arch, -f, --no-build, --no-restore, -p; добавьте --no-build, чтобы упаковать существующую сборку без повторной сборки.

Установка сертификата

Прежде чем установить пакет MSIX, необходимо установить сертификат разработки. Выполните следующую команду от имени администратора:

winapp cert install .\devcert.pfx

Установка и запуск

Установите пакет, дважды щелкнув созданный файл *.msix.

Теперь вы можете запустить приложение из любого места в терминале, введя следующее:

dotnet-app

Вы должны увидеть вывод "Package Family Name", подтверждающий его установку и запуск с удостоверением.

Подсказка

Если вам нужно перепаковать приложение (например, после изменения кода), увеличьте Version в вашем Package.appxmanifest перед выполнением winapp pack еще раз. Windows требуется более высокий номер версии для обновления установленного пакета.

Tips

  1. После подготовки к распространению вы можете подписать MSIX с помощью сертификата подписи кода из центра сертификации, чтобы пользователи не должны устанавливать самозаверяющий сертификат.
  2. Microsoft Store подпишет MSIX за вас, так что нет необходимости подписывать его перед отправкой.
  3. Может потребоваться создать несколько пакетов MSIX, по одному для каждой поддерживаемой архитектуры (x64, Arm64). Используйте флаг -r с dotnet build для нацеливания на конкретные архитектуры: dotnet build -c Release -r win-x64 или dotnet build -c Release -r win-arm64.

Автоматизация упаковки MSIX (необязательно)

Чтобы автоматизировать упаковку MSIX в рамках сборок выпуска, добавьте этот целевой элемент в .csproj файл (его можно добавить вместе с целевым элементом отладки).

  <!-- Automatically package as MSIX after Release builds -->
  <Target Name="PackageMsix" AfterTargets="Build" Condition="'$(Configuration)' == 'Release'">
    <!-- Package and sign directly from build output -->
    <Exec Command="winapp pack &quot;$(TargetDir.TrimEnd('\'))&quot; --cert &quot;$(ProjectDir)devcert.pfx&quot;" 
          WorkingDirectory="$(ProjectDir)" 
          IgnoreExitCode="false" />
  </Target>

С этой конфигурацией:

  • Создание в режиме выпуска (dotnet build -c Release) автоматически создаст пакет MSIX
  • MSIX упакован и подписан вашим сертификатом разработки.
  • Окончательный .msix файл будет находиться в корневом каталоге проекта.

Вы также можете создать настраиваемую конфигурацию (например, PackagedRelease), изменив условие '$(Configuration)' == 'PackagedRelease'на .

Дальнейшие шаги

  • Распространите с помощью winget: отправьте MSIX в репозиторий сообщества Windows диспетчер пакетов
  • Опубликовать в Microsoft Store: используйте winapp store для отправки пакета.
  • Set up CI/CD. Используйте действие setup-WinAppCli GitHub для автоматизации упаковки в конвейере.
  • Ознакомьтесь с Windows API: Теперь, с удостоверением пакета, вы можете использовать Уведомления, встроенный ИИ, и другие API-интерфейсы, зависящие от удостоверения