Skip to content

Windows installer configuration

NetWiv generates Windows x64 NSIS (nsis) and WiX v3 MSI (msi) installers. Build these on Windows, with NSIS 3.11 or later and WiX v3 (including WixUIExtension for directory selection) on PATH. These options apply equally to managed and NativeAOT applications; see deployment modes.

The following NetWiv-specific extension is shared by both formats. It is not an upstream TAURI® configuration contract. The CLI validates its types and keys; the extension schema describes this object for editors. Do not add these keys to the generated upstream compatibility schema.

{
"bundle": {
"active": true,
"targets": ["nsis", "msi"],
"windows": {
"installer": {
"scope": "perMachine",
"allowDirectorySelection": true,
"shortcuts": {
"name": "My App",
"arguments": ["--profile", "Production Line 1", ""],
"workingDirectory": ".",
"desktop": true,
"startMenu": true
}
}
}
}
}
Key under bundle.windows.installer Default Meaning
scope "currentUser" "currentUser" or "perMachine"; fixed when the package is built.
allowDirectorySelection false Show the NSIS directory page / MSI install-directory wizard.
shortcuts.name Product name + stable identity suffix Display name for both shortcuts, without .lnk. Explicit names are used as supplied.
shortcuts.arguments [] Literal argument array; supports spaces, Unicode, quotes, empty strings and trailing backslashes. No shell expansion.
shortcuts.workingDirectory "." Directory relative to the installation root, at most 1000 UTF-16 code units. Created during installation if absent.
shortcuts.desktop NSIS: true; MSI: false Create a desktop shortcut. Omit to retain the format’s previous default.
shortcuts.startMenu true Create a shortcut in the product’s identity-qualified Start menu folder.

The working directory must stay inside the install root: absolute paths, drive prefixes, .., empty segments and invalid Windows names are rejected. Shortcut names must be valid Windows filenames (up to 200 characters for NSIS, 115 for MSI including its generated short-name allowance). Argument strings cannot contain control characters; their quoted command line must fit 1000 UTF-16 code units (the standard NSIS string-buffer limit). MSI carries the command through a property so the shortcut table’s 255-character argument field does not truncate it. NSIS and MSI/WiX metacharacters are escaped independently of Windows argument quoting. Do not put shell syntax or installer variables in the array expecting expansion: $INSTDIR and [INSTALLDIR], for example, are passed literally to the app.

Windows Shell expands %NAME% in shortcut arguments. To preserve the literal argument contract, configurations containing more than one percent sign across all arguments are rejected; a single percent sign (for example 50%) is allowed.

NSIS rejects installation before copying files when the root plus the longest generated path (payload, executable, uninstaller or working directory) exceeds 1000 UTF-16 code units.

Unknown keys, nulls, wrong types, unknown scopes, and launch settings with all shortcuts disabled fail before build hooks, publishing or packaging tools run. For MSI, omitting desktop while setting startMenu: false also disables all shortcuts. Windows settings may remain in a shared cross-platform config; Linux/macOS bundles do not use them. Platform-incompatible bundle targets fail before build/bundle hooks run.

Behavior currentUser perMachine
Default directory Local application data + identity-qualified product folder 64-bit Program Files + identity-qualified product folder
Installer elevation No elevation requested Administrator required
Registration HKCU HKLM
Shortcuts Current user’s desktop / Start menu Common desktop / Start menu
Accepted Evergreen WebView2 registration Current user or machine Machine only

Installer elevation does not change the installed application’s manifest or make the application request administrator rights. Supply an application manifest through .NET/MSBuild when the app itself needs elevation.

Use a dedicated app directory to avoid file-name collisions. Both installers remove package-owned files and empty folders on uninstall; unrelated files inside the selected directory and application data outside it are preserved.

Default installation folders, Start menu folders and shortcut names include a stable 16-hex-character identity suffix, such as My App (0123456789ABCDEF). NSIS derives it from the application identifier and scope; MSI derives it from the canonical, scope-specific UpgradeCode. Generated names shorten the product name if necessary to fit each format’s filename limit, retaining the suffix and complete Unicode characters. The display name in installed-program registration is unchanged. This intentionally replaces the old product-name-only defaults: independent apps with the same display name must not overwrite each other’s payloads or shortcuts. Existing registered installation paths are still recovered on upgrade; the previous installer removes its old shortcuts before replacement. An explicit shortcuts.name is unchanged, so authors choosing one must avoid other applications’ desktop shortcut names. Likewise, a custom installation path must not point into another application’s directory.

Subsequent installations of the same format, scope and identity recover the stored installation directory. MSI versions predating this feature did not store InstallLocation and therefore cannot recover an earlier custom path. NSIS can recover the previous version’s uninstall registration. New NSIS packages remove the previous package-owned files before installing an upgrade, including files omitted by the new version. Legacy packages have no ownership metadata: their recursive uninstallers are never run automatically, so obsolete files from those versions may require manual cleanup. Relocating a legacy NSIS installation is rejected until it is uninstalled explicitly. New packages support relocation and remove the old uninstaller along with the old payload. Keep the identifier, product name and MSI wix.upgradeCode stable across upgrades. Equivalent GUID spellings (case or braces) retain the same upgrade identity. MSI component identities are scoped to that upgrade identity. Independent packages with the same display name must configure distinct wix.upgradeCode values; the backward-compatible default is derived from the display name. Machine MSI packages have a separate upgrade identity, so changing scope is not a migration of an existing user installation. Uninstall the old installation before changing scope or switching between MSI and NSIS. Both formats are alternative distribution choices, not two installers to run for the same app.

Silent directory overrides take precedence over the recovered path:

Terminal window
# /D must be last, without surrounding quotes, even when the path contains spaces.
.\MyApp-setup.exe /S /D=C:\Apps\My App
msiexec /i MyApp.msi /qn INSTALLDIR="C:\Apps\My App"

Omit the override on the next install to reuse that path. Directory selection is opt-in for interactive users; silent overrides do not require an interactive page.

The WebView2 check does not download or install a runtime. If it is absent, NSIS returns code 2 in silent mode; MSI fails its launch condition. Interactive NSIS can open Microsoft’s download page with consent. Uninstallation remains possible when WebView2 has subsequently been removed. Framework-dependent apps also need the corresponding .NET runtime installed separately.

If an owned file is locked or cannot be deleted, NSIS removal returns code 2 and an upgrade stops before installing the new payload. Registration, shortcuts and the old uninstaller remain available for retry. Close the application and retry the removal or upgrade. Removal is not transactional: files deleted before the failure are not rolled back; a successful upgrade retry installs the new payload.

Windows CI uses node scripts/prepare-nsis.mjs to download the official portable NSIS 3.11 archive, verify its pinned SHA-256 and compiler version, and add the compiler to PATH for subsequent steps. It does not require Chocolatey.

Cross-platform CLI tests validate config failures, argument quoting and both installer renderers. scripts/test-windows-installers.ps1 runs on a disposable, elevated Windows CI runner: real NSIS/WiX compilation, both scopes, rejection of missing/user-only prerequisites, actual shortcut launches recording arguments and working directory, custom-path upgrade, and uninstall preserving unrelated and external application data. It uses a small NativeAOT probe; WebView GUI smoke is a separate CI gate. Interactive directory browsing and a standard user’s UAC consent flow still require manual acceptance; silent elevated CI does not prove those flows. The tests also hold an obsolete file open during NSIS removal/upgrade, verify failure and retry after releasing the lock, and install two independent MSI products with the same display name to verify uninstall and shortcut isolation. Coexistence tests omit both shortcut names and installation-directory overrides, cover MSI and NSIS in both scopes, launch both default shortcuts, and remove the products in both orders while checking that the survivor still launches.

For local acceptance on a dedicated Windows validation machine, install NSIS 3.11, WiX 3.14.1, .NET 8 SDK and the Visual C++ build tools, then run from an elevated PowerShell 7 terminal with the packaging tools on PATH:

Terminal window
dotnet build src/NetWiv.Cli -c Release
./scripts/test-windows-installers.ps1 -AllowLocalMachine

The explicit local flag is required outside CI. The test temporarily changes the WebView2 pv values, then restores their original value/type and removes registry keys created by the test, including on failure. Use a dedicated test machine.


TAURI® is a trademark of The Tauri Programme within the Commons Conservancy. NetWiv is an independent project and is not affiliated with or endorsed by it.