| title | Using winapp CLI with .NET |
|---|---|
| description | Learn how to use the winapp CLI with .NET applications (console, WPF, WinForms) to add package identity, access Windows APIs, and package as MSIX. |
| ms.date | 02/20/2026 |
| ms.topic | how-to |
Note
This guide works for most .NET project types. The steps have been tested with both console and UI-based projects like WPF.
This guide demonstrates how to use the winapp CLI with a .NET application to debug with package identity and package your application as an MSIX.
Package identity is a core concept in the Windows app model. It allows your application to access specific Windows APIs (like Notifications, Security, AI APIs, etc.), have a clean install/uninstall experience, and more.
-
.NET SDK: Install the .NET SDK:
winget install Microsoft.DotNet.SDK.10 --source winget
-
winapp CLI: Install the
winapptool via winget:winget install Microsoft.winappcli --source winget
Start by creating a simple .NET console application:
dotnet new console -n dotnet-app
cd dotnet-appRun it to make sure everything is working:
dotnet runFirst, update your project file to target a specific Windows SDK version. Open dotnet-app.csproj and change the TargetFramework:
<TargetFramework>net10.0-windows10.0.26100.0</TargetFramework>Now replace the contents of Program.cs:
using Windows.ApplicationModel;
try
{
var package = Package.Current;
var familyName = package.Id.FamilyName;
Console.WriteLine($"Package Family Name: {familyName}");
}
catch (InvalidOperationException)
{
Console.WriteLine("Not packaged");
}dotnet runYou should see "Not packaged".
The winapp init command automatically detects .csproj files and runs a .NET-specific setup:
winapp initWhen prompted:
- Package name: Press Enter to accept the default
- Publisher name: Press Enter to accept the default or enter your name
- Description: Press Enter to accept the default or enter a description
- Version: Press Enter to accept 1.0.0.0
- Entry point: Press Enter to accept the default (dotnet-app.exe)
- Windows App SDK setup: Select Stable, Preview, or Experimental
This command:
- Updates the
TargetFrameworkin your.csprojto a supported Windows TFM (if needed) - Adds
Microsoft.WindowsAppSDKandMicrosoft.Windows.SDK.BuildToolsNuGet package references - Creates
appxmanifest.xmlandAssetsfolder for your app identity
Note
Unlike native/C++ projects, the .NET flow does not create a winapp.yaml file. NuGet packages are managed directly via your .csproj. Use dotnet restore to restore packages after cloning.
-
Build the executable:
dotnet build -c Debug -
Apply debug identity:
winapp create-debug-identity .\bin\Debug\net10.0-windows10.0.26100.0\dotnet-app.exe
-
Run the executable (do not use
dotnet runas it might rebuild):.\bin\Debug\net10.0-windows10.0.26100.0\dotnet-app.exe
You should see:
Package Family Name: dotnet-app_12345abcde
Add this target to your .csproj file:
<Target Name="ApplyDebugIdentity" AfterTargets="Build" Condition="'$(Configuration)' == 'Debug'">
<Exec Command="winapp create-debug-identity "$(TargetDir)$(TargetName).exe""
WorkingDirectory="$(ProjectDir)"
IgnoreExitCode="false" />
</Target>If you ran winapp init, Microsoft.WindowsAppSDK was already added as a NuGet package reference. Update Program.cs to use the Windows App Runtime API:
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}");
var runtimeVersion = Microsoft.Windows.ApplicationModel.WindowsAppRuntime.RuntimeInfo.AsString;
Console.WriteLine($"Windows App Runtime Version: {runtimeVersion}");
}
catch (InvalidOperationException)
{
Console.WriteLine("Not packaged");
}
}
}-
Build for release:
dotnet build -c Release -
Generate a development certificate:
winapp cert generate --if-exists skip
-
Package and sign:
winapp pack .\bin\Release\net10.0-windows10.0.26100.0 --manifest .\appxmanifest.xml --cert .\devcert.pfx
-
Install the certificate (run as administrator):
winapp cert install .\devcert.pfx
-
Install by double-clicking the generated
.msixfile.
Tip
- The Microsoft Store signs the MSIX for you, no need to sign before submission.
- You may need separate MSIX packages for each architecture:
dotnet build -c Release -r win-x64ordotnet build -c Release -r win-arm64.
Add this target to your .csproj:
<Target Name="PackageMsix" AfterTargets="Build" Condition="'$(Configuration)' == 'Release'">
<Exec Command="winapp pack "$(TargetDir.TrimEnd('\'))" --cert "$(ProjectDir)devcert.pfx""
WorkingDirectory="$(ProjectDir)"
IgnoreExitCode="false" />
</Target>