Skip to content

Commit bcfc9db

Browse files
committed
Add multi-headed MSIX package sample apps
Add two sample apps demonstrating multiple Application elements in a single package manifest, supporting the multi-headed MSIX packaging feature (WindowsAppSDK #5586): - cs-winui-msix: WinUI 3 primary app + console secondary app in one MSIX package via single-project packaging - cs-wpf-sparse: WPF primary app with register/unregister UI + WPF secondary app in one sparse package
1 parent c700667 commit bcfc9db

28 files changed

Lines changed: 754 additions & 0 deletions
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
---
2+
page_type: sample
3+
languages:
4+
- csharp
5+
products:
6+
- windows
7+
- windows-app-sdk
8+
name: "Multi-headed MSIX package sample"
9+
urlFragment: multi-headed-package
10+
description: "Shows how to package multiple executables in a single MSIX or sparse package"
11+
extendedZipContent:
12+
- path: LICENSE
13+
target: LICENSE
14+
---
15+
# Multi-headed MSIX package sample
16+
17+
These samples demonstrate how to create **multi-headed packages** — MSIX or sparse packages that contain multiple `<Application>` elements in a single `Package.appxmanifest`. Each application entry gets its own Start menu tile and can be launched independently, while sharing the same package identity and installation lifecycle.
18+
19+
## Samples
20+
21+
### MSIX sample (`cs/cs-winui-msix/`)
22+
23+
A WinUI 3 solution using single-project MSIX packaging with two projects:
24+
25+
- **PrimaryApp** — The main WinUI app that owns the package manifest. Uses `$targetnametoken$` tokens so the build system fills in the correct executable name.
26+
- **SecondaryApp** — A secondary WinUI app referenced by PrimaryApp. Its executable name is hardcoded in the manifest as `SecondaryApp.exe` with `EntryPoint="Windows.FullTrustApplication"`.
27+
28+
After deployment, both apps appear in the Start menu as separate entries.
29+
30+
### Sparse sample (`cs/cs-wpf-sparse/`)
31+
32+
A WPF solution demonstrating multi-headed sparse packages with runtime registration:
33+
34+
- **PrimaryApp** — A WPF app with `WindowsPackageType=Sparse` that includes Register/Unregister/Restart buttons to manage the sparse package at runtime.
35+
- **SecondaryApp** — A minimal WPF app that detects whether it has package identity (which it will once the sparse package is registered).
36+
37+
## Prerequisites
38+
39+
* See [System requirements for Windows app development](https://docs.microsoft.com/windows/apps/windows-app-sdk/system-requirements).
40+
* Make sure that your development environment is set up correctly&mdash;see [Install tools for developing apps for Windows 10 and Windows 11](https://docs.microsoft.com/windows/apps/windows-app-sdk/set-up-your-development-environment).
41+
42+
## Building and running
43+
44+
### MSIX sample
45+
46+
1. Open `cs/cs-winui-msix/MultiHeadedMsix.sln` in Visual Studio.
47+
2. Set **PrimaryApp** as the startup project.
48+
3. Press **F5** to build, deploy, and launch the primary app.
49+
4. Check the Start menu for both "Primary App" and "Secondary App" entries.
50+
51+
### Sparse sample
52+
53+
1. Open `cs/cs-wpf-sparse/MultiHeadedSparse.sln` in Visual Studio.
54+
2. Set **PrimaryApp** as the startup project.
55+
3. Press **Ctrl+F5** to run without debugging.
56+
4. Click **Register Package** to register the sparse package.
57+
5. Click **Restart** to relaunch with package identity.
58+
6. Run **SecondaryApp** separately to verify it also detects the package identity.
59+
60+
## Related links
61+
62+
- [Windows App SDK](https://docs.microsoft.com/windows/apps/windows-app-sdk/)
63+
- [Single-project MSIX packaging](https://docs.microsoft.com/windows/apps/windows-app-sdk/single-project-msix)
64+
- [Sparse packages](https://docs.microsoft.com/windows/apps/desktop/modernize/grant-identity-to-nonpackaged-apps)
65+
- [WindowsAppSDK issue #5586](https://github.com/microsoft/WindowsAppSDK/issues/5586)
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.0.31717.71
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PrimaryApp", "PrimaryApp\PrimaryApp.csproj", "{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}"
7+
EndProject
8+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SecondaryApp", "SecondaryApp\SecondaryApp.csproj", "{B2C3D4E5-F6A7-8901-BCDE-F12345678901}"
9+
EndProject
10+
Global
11+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
12+
Debug|ARM64 = Debug|ARM64
13+
Debug|x64 = Debug|x64
14+
Debug|x86 = Debug|x86
15+
Release|ARM64 = Release|ARM64
16+
Release|x64 = Release|x64
17+
Release|x86 = Release|x86
18+
EndGlobalSection
19+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
20+
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|ARM64.ActiveCfg = Debug|ARM64
21+
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|ARM64.Build.0 = Debug|ARM64
22+
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|ARM64.Deploy.0 = Debug|ARM64
23+
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|x64.ActiveCfg = Debug|x64
24+
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|x64.Build.0 = Debug|x64
25+
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|x64.Deploy.0 = Debug|x64
26+
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|x86.ActiveCfg = Debug|x86
27+
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|x86.Build.0 = Debug|x86
28+
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|x86.Deploy.0 = Debug|x86
29+
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|ARM64.ActiveCfg = Release|ARM64
30+
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|ARM64.Build.0 = Release|ARM64
31+
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|x64.ActiveCfg = Release|x64
32+
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|x64.Build.0 = Release|x64
33+
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|x86.ActiveCfg = Release|x86
34+
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|x86.Build.0 = Release|x86
35+
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Debug|ARM64.ActiveCfg = Debug|ARM64
36+
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Debug|ARM64.Build.0 = Debug|ARM64
37+
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Debug|x64.ActiveCfg = Debug|x64
38+
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Debug|x64.Build.0 = Debug|x64
39+
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Debug|x86.ActiveCfg = Debug|x86
40+
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Debug|x86.Build.0 = Debug|x86
41+
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Release|ARM64.ActiveCfg = Release|ARM64
42+
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Release|ARM64.Build.0 = Release|ARM64
43+
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Release|x64.ActiveCfg = Release|x64
44+
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Release|x64.Build.0 = Release|x64
45+
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Release|x86.ActiveCfg = Release|x86
46+
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Release|x86.Build.0 = Release|x86
47+
EndGlobalSection
48+
GlobalSection(SolutionProperties) = preSolution
49+
HideSolutionNode = FALSE
50+
EndGlobalSection
51+
GlobalSection(ExtensibilityGlobals) = postSolution
52+
SolutionGuid = {D1E2F3A4-B5C6-7890-DEFA-123456789ABC}
53+
EndGlobalSection
54+
EndGlobal
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<!-- Copyright (c) Microsoft Corporation.
2+
Licensed under the MIT License. -->
3+
<Application
4+
x:Class="PrimaryApp.App"
5+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
6+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
7+
xmlns:local="using:PrimaryApp">
8+
</Application>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
using Microsoft.UI.Xaml;
5+
6+
namespace PrimaryApp
7+
{
8+
public partial class App : Application
9+
{
10+
private Window mainWindow;
11+
12+
public App()
13+
{
14+
this.InitializeComponent();
15+
}
16+
17+
protected override void OnLaunched(LaunchActivatedEventArgs args)
18+
{
19+
mainWindow = new MainWindow();
20+
mainWindow.Activate();
21+
}
22+
}
23+
}
76.3 KB
Loading
10.6 KB
Loading
2.73 KB
Loading
10.9 KB
Loading
3.06 KB
Loading
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<!-- Copyright (c) Microsoft Corporation.
2+
Licensed under the MIT License. -->
3+
<Window
4+
x:Class="PrimaryApp.MainWindow"
5+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
6+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
7+
Title="Primary App - Multi-Headed MSIX">
8+
9+
<Grid VerticalAlignment="Center" HorizontalAlignment="Center">
10+
<StackPanel Spacing="16">
11+
<TextBlock
12+
Text="This is the Primary App"
13+
FontSize="28"
14+
HorizontalAlignment="Center" />
15+
<TextBlock
16+
Text="This app is part of a multi-headed MSIX package."
17+
FontSize="16"
18+
HorizontalAlignment="Center"
19+
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
20+
<TextBlock
21+
Text="Check your Start menu for both 'Primary App' and 'Secondary App' entries."
22+
FontSize="14"
23+
HorizontalAlignment="Center"
24+
Foreground="{ThemeResource TextFillColorTertiaryBrush}"
25+
TextWrapping="Wrap"
26+
TextAlignment="Center" />
27+
</StackPanel>
28+
</Grid>
29+
</Window>

0 commit comments

Comments
 (0)