Context
Use this when a desktop app adds an MSI installer and the slice specifically requires standard-user, non-admin installation.
Pattern
- Require one repo-root build command that produces the MSI artifact deterministically.
- Verify installer metadata really declares per-user scope and limited privileges for the packaging tool in use.
- Treat the installed payload as the product: confirm the installed directory contains the app exe, runtime files, bundled content, and supporting assemblies.
- If the ask is for a single-file MSI, verify the Release output directory contains the
.msiand no sibling external.cab; do not infer this only from WiX metadata. If possible, corroborate with the built MSIMediatable showing an embedded cabinet entry such as#cab1.cab. - Run one install/launch/uninstall cycle from a non-elevated user context.
- Re-run the existing app regression baseline so packaging work does not quietly break the app itself.
- Check that mutable app data remains user-scoped and is not removed accidentally on uninstall.
- After first launch, inspect the install root for app-created runtime caches (especially WebView2
*.exe.WebView2folders). If launch repopulates the install directory, the lifecycle is not clean enough to trust.
Good signs
- No UAC prompt during install or uninstall
- Install location is under a user profile path rather than
Program Files - Release output contains the MSI only, with no external cabinet beside it
- Installed app launches successfully from the installed path or shortcut
- Existing solution tests and Web UI build still pass
- First launch does not create runtime profile/cache data under the install folder
Anti-patterns
- Trusting an MSI only because the file exists
- Assuming
Compressed="yes"or aMediaTemplatechange automatically means "single-file MSI" without checking the actual build output - Building the installer from hand-staged binaries outside the repo workflow
- Verifying the build output directory but never launching the installed copy
- Allowing uninstall to remove user data without an explicit, documented choice
- Ignoring framework-default runtime caches that respawn inside the install folder after launch