winapp-package

Package a Windows app as an MSIX installer for distribution or testing. Use when creating a Windows installer, packaging an Electron/Flutter/.NET/Rust/C++/Tauri app for Windows, building an MSIX, distributing a desktop app, packaging a console app or CLI tool, or adding MSIX packaging to a build script or CI/CD pipeline.

microsoft/winappcli7 installsMITSynced Aug 25

Works with

Claude CodeCursorCodex CLIGitHub CopilotGemini CLI
---
name: winapp-package
description: Package a Windows app as an MSIX installer for distribution or testing. Use when creating a Windows installer, packaging an Electron/Flutter/.NET/Rust/C++/Tauri app for Windows, building an MSIX, distributing a desktop app, packaging a console app or CLI tool, or adding MSIX packaging to a build script or CI/CD pipeline.
license: MIT
---

## When to use

Use this skill when:
- **Creating an MSIX installer** from a built app for distribution or testing
- **Packaging any Windows app** — GUI apps, console apps, CLI tools, services, or background processes
- **Signing a package** with a development or production certificate
- **Bundling the Windows App SDK runtime** for self-contained deployment

## Prerequisites

Before packaging, you need:
1. **Built app output** in a folder (e.g., `bin/Release/`, `dist/`, `build/`)
2. **`Package.appxmanifest`** — from `winapp init` or `winapp manifest generate`
3. **Certificate** (optional) — `devcert.pfx` from `winapp cert generate` for signing

## Usage

### Basic packaging (unsigned)

```powershell
# Package from build output — manifest auto-detected from current dir or input folder
winapp package ./bin/Release

# Specify manifest location explicitly
winapp package ./dist --manifest ./Package.appxmanifest
```

### Package and sign in one step

```powershell
# Sign with existing certificate
winapp package ./bin/Release --cert ./devcert.pfx

# Custom certificate password
winapp package ./bin/Release --cert ./devcert.pfx --cert-password MyP@ssw0rd
```

### Generate certificate + package in one step

```powershell
# Auto-generate cert, sign, and package
winapp package ./bin/Release --generate-cert

# Also install the cert to trust it on this machine (requires admin)
winapp package ./bin/Release --generate-cert --install-cert
```

### Self-contained deployment

```powershell
# Bundle Windows App SDK runtime so users don't need it installed (must have winappsdk reference in the winapp.yaml or *.csproj)
winapp package ./bin/Release --cert ./devcert.pfx --self-contained
```

### Custom output path and name

```powershell
# Specify output file
winapp package ./dist --output ./releases/myapp-v1.0.msix --cert ./devcert.pfx

# Custom package name
winapp package ./dist --name "MyApp_1.0.0_x64" --cert ./devcert.pfx
```

## What the command does

1. **Locates `Package.appxmanifest`** — looks in input folder, then current directory (or uses `--manifest`)
2. **Copies manifest + assets** into a staging layout alongside your app files
3. **Discovers manifest-referenced files** — any non-image file referenced in the manifest (e.g., AppExtension payloads like `manifest.json`, config files) is automatically copied from the manifest directory or input folder if missing from staging
4. **Generates `resources.pri`** — Package Resource Index for UWP-style resource lookup (skip with `--skip-pri`)
5. **Runs `makeappx pack`** — creates the `.msix` package file
6. **Signs the package** (if `--cert` provided) — calls `signtool` with your certificate

Output: a `.msix` file that can be installed on Windows via double-click or `Add-AppxPackage`.

## Installing the MSIX for testing

```powershell
# Trust the dev certificate first (one-time, requires admin)
winapp cert install ./devcert.pfx

# Install the MSIX
Add-AppxPackage ./myapp.msix

# Uninstall if needed
Get-AppxPackage *myapp* | Remove-AppxPackage
```

## Recommended workflow

1. **Build** your app (`dotnet build`, `cmake --build`, `npm run make`, etc.)
2. **Package** — `winapp package <build-output> --cert ./devcert.pfx`
3. **Trust cert** (first time) — `winapp cert install ./devcert.pfx` (admin)
4. **Install** — double-click the `.msix` or `Add-AppxPackage ./myapp.msix`
5. **Test** the installed app from the Start menu

### Advanced: External content catalog

For sparse packages with `AllowExternalContent`, you may need a code integrity catalog:

```powershell
# Generate CodeIntegrityExternal.cat for external executables
winapp create-external-catalog "./bin/Release"

# Include subdirectories and specify output path
winapp create-external-catalog "./bin/Release" --recursive --output ./catalog/CodeIntegrityExternal.cat
```

### Bundling multiple architectures

Create an MSIX bundle from multiple per-architecture build outputs:

```powershell
# Create unsigned bundle for Store submission (x64 + arm64)
winapp package ./publish/x64 ./publish/arm64

# Create signed bundle for sideloading
winapp package ./publish/x64 ./publish/arm64 --cert ./devcert.pfx

# Self-contained bundle with Windows App SDK runtime per arch
winapp package ./publish/x64 ./publish/arm64 --self-contained --generate-cert
```

**How it works:** When multiple input folders are passed, `winapp package`:
1. Detects the architecture of each folder's primary executable from its PE header
2. Resolves a manifest for each slice (see below)
3. Validates that all slices share the same Identity, Capabilities, and Dependencies
4. Packs each folder into an intermediate unsigned `.msix`
5. Bundles them into a single `.msixbundle` using `makeappx bundle`
6. Signs only the bundle (not individual slices) — the signature covers all packages inside

**Manifest resolution:** Each slice needs a manifest. Resolution order:
- `--manifest <path>` uses one manifest for all slices (architecture auto-stamped per folder)
- Per-folder `Package.appxmanifest` if present in the input folder
- Fallback to `Package.appxmanifest` in the current working directory

The `ProcessorArchitecture` is always force-set to the detected architecture per-slice. All other Identity fields must be consistent across slices.

**Output:** `<Name>_<Version>_<arch1>_<arch2>.msixbundle` (architectures sorted alphabetically).

**Store submission:** An unsigned bundle is valid for Store upload — Partner Center signs it with your reserved identity certificate. For sideloading, pass `--cert` or `--generate-cert`.

This hashes executables in the specified directories so Windows trusts them when running with sparse package identity.

## CI/CD

### GitHub Actions

Use the `microsoft/setup-winapp` action to install winapp on GitHub-hosted runners:

```yaml
- uses: microsoft/setup-winapp@v1

- name: Package
  run: winapp package ./dist --cert ${{ secrets.CERT_PATH }} --cert-password ${{ secrets.CERT_PASSWORD }} --quiet
```

**Tips for CI/CD pipelines:**
- Use `--quiet` (or `-q`) to suppress progress output
- Use `--if-exists skip` with `winapp cert generate` to avoid regenerating existing certificates
- Store your PFX certificate as a repository secret and decode it in CI
- Use `--use-defaults` (or `--no-prompt`) with `winapp init` to avoid interactive prompts

## Tips

- The `package` command aliases to `pack` — both work identically
- `Package.appxmanifest` Publisher must match the certificate publisher — use `winapp cert generate --manifest` to ensure they match
- Use `--skip-pri` if your app doesn't use Windows resource loading (e.g., most Electron/Rust/C++ apps without UWP resources)
- For framework-specific packaging paths (Electron, .NET, Rust, etc.), see the `winapp-frameworks` skill
- The `--executable` flag overrides the entry point in the manifest — useful when your exe name differs from what's in `Package.appxmanifest`
- For production distribution, use a certificate from a trusted CA and add `--timestamp` when signing with `winapp sign`

## Related skills
- Need a manifest first? See `winapp-manifest` to generate `Package.appxmanifest`
- Need a certificate? See `winapp-signing` for certificate generation and management
- Having issues? See `winapp-troubleshoot` for a command selection flowchart and error solutions

## Troubleshooting
| Error | Cause | Solution |
|-------|-------|----------|
| "Package.appxmanifest not found" | No manifest in input folder or current dir | Run `winapp init` or `winapp manifest generate` first |
| "Publisher mismatch" | Cert publisher ≠ manifest publisher | Regenerate cert with `winapp cert generate --manifest`, or edit manifest |
| "Package installation failed" | Cert not trusted or stale package | Run `winapp cert install ./devcert.pfx` (admin), then `Get-AppxPackage <name> \| Remove-AppxPackage` |
| "makeappx not found" | Build tools not downloaded | Run `winapp update` or `winapp tool makeappx --help` to trigger download |


## Command Reference

### `winapp package`

Create MSIX installer from your built app. Run after building your app. A manifest (Package.appxmanifest or appxmanifest.xml) is required for packaging - it must be in current working directory, passed as --manifest or be in the input folder. Use --cert devcert.pfx to sign for testing. Example: winapp package ./dist --manifest Package.appxmanifest --cert ./devcert.pfx

**Aliases:** `pack`

#### Arguments
<!-- auto-generated from cli-schema.json -->
| Argument | Required | Description |
|----------|----------|-------------|
| `<input-folder>` | Yes | One or more input folders with package layout. Pass multiple folders to create an MSIX bundle (e.g., winapp pack ./publish/x64 ./publish/arm64). |

#### Options
<!-- auto-generated from cli-schema.json -->
| Option | Description | Default |
|--------|-------------|---------|
| `--cert` | Path to signing certificate (will auto-sign if provided) | (none) |
| `--cert-password` | Certificate password (default: password) | `password` |
| `--executable` | Path to the executable relative to the input folder. | (none) |
| `--generate-cert` | Generate a new development certificate | (none) |
| `--install-cert` | Install certificate to machine | (none) |
| `--manifest` | Path to AppX manifest file (default: auto-detect from input folder or current directory) | (none) |
| `--name` | Package name (default: from manifest) | (none) |
| `--output` | Output file name for the generated package (.msix) or bundle (.msixbundle). Defaults to <name>_<version>_<arch>.msix for single packages, or <name>_<version>_<arch1>_<arch2>.msixbundle for bundles. | (none) |
| `--publisher` | Publisher distinguished name (DN) for certificate generation (e.g., CN=MyCompany). Bare names are auto-wrapped as CN=<name>. | (none) |
| `--self-contained` | Bundle Windows App SDK runtime for self-contained deployment | (none) |
| `--skip-pri` | Skip PRI file generation | (none) |

### `winapp create-external-catalog`

Generates a CodeIntegrityExternal.cat catalog file with hashes of executable files from specified directories. Used with the TrustedLaunch flag in MSIX sparse package manifests (AllowExternalContent) to allow execution of external files not included in the package.

#### Arguments
<!-- auto-generated from cli-schema.json -->
| Argument | Required | Description |
|----------|----------|-------------|
| `<input-folder>` | Yes | List of input folders with executable files to process (separated by semicolons) |

#### Options
<!-- auto-generated from cli-schema.json -->
| Option | Description | Default |
|--------|-------------|---------|
| `--compute-flat-hashes` | Include flat hashes when generating the catalog | (none) |
| `--if-exists` | Behavior when output file already exists | `Error` |
| `--output` | Output catalog file path. If not specified, the default CodeIntegrityExternal.cat name is used. | (none) |
| `--recursive` | Include files from subdirectories | (none) |
| `--use-page-hashes` | Include page hashes when generating the catalog | (none) |

More Testing skills

← All Testing skills

Check your AI visibility

One URL in, a 0–100 score and the exact fixes out.

RUN THE CHECK

Browse all the tools

15 tools across six categories
13 of them never send your data anywhere

Free · No signup · No trial clock

SEE THE DIRECTORY