Following my previous post where I explored different packaging options for Win32 and UWP apps, I realised that there are some options I didn’t mention. In this post I’m going to provide a very quick summary of the options I’ve come across and how they define the running context of an app. Here goes….
Vanilla Win32
For example WinForms or WPF application where a user can launch the application by double-clicking the executable
Integrity Level: Medium
AppContainer: No
Has Identity: No
Vanilla Win32 (Run as Admin)
Right-click on the WinForms or WPF application and select Run as Administrator
Integrity Level: High
AppContainer: No
Has Identity: No
Win32 Packaged Full-Trust
Uses the Windows Application Packaging project with default Trust Level set to Full Trust
Integrity Level: Medium
AppContainer: No
Has Identity: Yes
Other: Whilst the trust level is supposedly full trust, there is in fact a proxy layer in place for the Registry and parts of the file system (useful reference)
Win32 Packaged Partial-Trust
Set the Trust Level in the Windows Application Packaging project to Partial Trust
Integrity Level: Low
AppContainer: Yes
Has Identity: Yes
Win32 with Sparse Package
Unpackaged Win32 application with package that has allowExternalContent set to true in the package manifest (referred to as a Sparse Package). Application needs to register the Sparse Package on first run (and subsequently unregister as part of clean up).
Integrity Level: Medium
AppContainer: No
Has Identity: Yes
Other: Unlike a packaged Win32 app, in this case the app is not subject to filesystem + registry virtualization, lifetime management by the system and other runtime attributes of fully packaged applications
More information can be found in the docs and in this blog post
Vanilla UWP
This is just an app built from one of the Universal Windows templates in Visual Studio.
Integrity Level: Low
AppContainer: Yes
Has Identity: Yes
UWP with Full Trust Capability
Add the runFullTrust capability in the package.manifest
Integrity Level: Low
AppContainer: Yes
Has Identity: Yes
Note: Essentially adding the runFullTrust capability doesn’t affect the UWP application, other than requesting an additional capability when the user goes to install the application. Do not include this capability unless you are packaging a Win32 app/extension that needs to run outside the appcontainer.
UWP with Full Trust Capability and Win32 App/Extension
In addition to the runFullTrust capability being added to the package.manifest file, a Win32 app or extension has been packaged alongside the UWP application.
Integrity Level (UWP App): Low
AppContainer (UWP App): Yes
Has Identity (UWP App): Yes
Integrity Level (Win32): Medium
AppContainer (Win32): No
Has Identity (Win32): Yes
Other: As with Win32 Packaged Full-Trust, the Win32 app/extension is subject to filesystem and registry virtualization.
Stefan Wick has a number of great posts covering this topic and are a must read if you’re going down this path of extending your UWP application with a Win32 component.
- UWP with Desktop Extension – Part 1
- UWP with Desktop Extension – Part 2
- UWP app with Systray extension
- UWP with Desktop Extension – Part 3
- App Elevation Samples – Part 1
- Global hotkey registration in UWP
- App Elevation Samples – Part 2
- App Elevation Samples – Part 3
- Creating chromeless, non-rectangular Windows from UWP
- UWP with Desktop Extension – Part 4
Summary
As you can see there are a large number of options when it comes to building for Windows. With projects like WinUI and Project Reunion this landscape will get easier to navigate.
>Win32 with Sparse Package – Unpackaged Win32 application with package that has allowExternalContent set to true in the package manifest
This is incorrect, conflating 2 separate features — RuntimeBehavior=win32App and ExternalLocation.
Any MSIX package can be installed with an ExternalLocation. That just tells Windows this package’s CONTENT files can be found at this other path (the package’s FOOTPRINT files are expected at the usual package location e.g. %ProgramFiles%\WindowsApps\…pkgfullname…).
An MSIX package’s FOOTPRINT files are the well-defined MSIX metadata files — appxmanifest.xml, appxblockmap.xml, signature.p7x, etc.
An MSIX package’s CONTENT files are everything else — *.exe, *.png, data files, etc.
A totally separate matter is how what sort of process is created at activation, most readily distinguish via uap10:RuntimeBehavior = windowsApp (aka UWP app), packagedClassicApp (aka Desktop Bridge) or win32 app.
A packaged process’ runtime behavior and whether it has an External Location are entirely independent and can be mixed and matched in any permutation you desire.
You can find more info at
* https://github.com/microsoft/WindowsAppSDK/discussions/2195
* https://github.com/microsoft/WindowsAppSDK/discussions/410 (especially https://github.com/microsoft/WindowsAppSDK/discussions/410#discussioncomment-368163)
* https://learn.microsoft.com/en-us/uwp/schemas/appxpackage/uapmanifestschema/element-application
P.S. That blog post you link to incorrectly conflates ExternalLocation and RB=win32app. I’ve filed a bug to improve docs.
P.P.S. A “Sparse Package” isn’t anything special. What matters is “Does a package have an External Location or not”. You could make an MSIX package containing a zillion content files, but if the package has an ExternalLocation none of those content files will be used in the package’s installed location (e.g. %ProgramFiles%\WindowsApps\pkgfullname). Thus if you intend a package to be installed with an ExternalLocation there’s no point putting your content files into the .msix, and thus you may as well avoid the wasted disk space and only include footprint files in the .msix. And thus, your .msix is a ‘sparse’ package. As in, it only contains a fraction of the package’s files (footprint yes, content no).
A package without content files isn’t all that new or magical. It’s always been possible. It’s just not very interesting to have a package of only footprint files…until External Location came along.
External Location is the key. The package being ‘sparse’ is a minor secondary detail.