Environment variables
Set Windows environment variables during install and tear them down on uninstall.
Applies to: MSI and MSIX (with MSI offering finer-grained control through the optional msi sub-object on each entry).
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | yes | – | Variable name (no % signs). |
value | string | yes | – | Variable value. Supports %expansion% and MSI [Property] substitution. |
msi | object | no | see defaults below | MSI-only configuration: scope, install/uninstall actions, value action. |
msi sub-object
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type | enum | no | System | System (machine-wide HKLM) or User (per-user HKCU). |
onInstall | enum | no | CreateOrUpdate | Create, CreateOrUpdate, or Remove. What happens to the variable on install. |
onUninstall | enum | no | Remove | Remove or Keep. What happens to the variable on uninstall. |
valueAction | enum | no | AppendEnd | Replace, AppendStart, AppendEnd. How value interacts with an existing value (use Replace when you want a single value, AppendStart/AppendEnd for PATH-like lists). |
For MSIX, the variable is set as a Win32 environment variable visible inside the MSIX container. The msi sub-object is ignored for MSIX builds.
Examples
Simple system variable
"environmentVariables": [
{
"name": "MY_COMPANY_HOME",
"value": "%ProgramFiles%\\My Application"
}
]
Default MSI behavior: System scope, CreateOrUpdate on install, Remove on uninstall, AppendEnd value action. For a single-value variable like a "home" path you almost certainly want valueAction: "Replace" instead – see next.
Replace (overwrite) the variable
{
"name": "MY_COMPANY_HOME",
"value": "[INSTALLDIR]",
"msi": {
"type": "System",
"onInstall": "CreateOrUpdate",
"onUninstall": "Remove",
"valueAction": "Replace"
}
}
Append to PATH
{
"name": "PATH",
"value": "[INSTALLDIR]\\bin",
"msi": {
"type": "System",
"onInstall": "CreateOrUpdate",
"onUninstall": "Remove",
"valueAction": "AppendEnd"
}
}
This is the canonical "add my CLI to the user's PATH" pattern. Notes:
valueAction: "AppendEnd"is the default, so you can omit themsiblock entirely if these are the only settings you need.- Values are appended with the platform separator (
;on Windows). MPDEV handles this for you. - Keep the
onUninstall: "Remove"default so your entry comes out cleanly. MPDEV strips its appended segment without touching anything else inPATH.
Per-user variable
{
"name": "MY_COMPANY_USERDATA",
"value": "%USERPROFILE%\\My Application",
"msi": {
"type": "User",
"onInstall": "CreateOrUpdate",
"onUninstall": "Keep"
}
}
Setting type: "User" writes to the per-user environment. onUninstall: "Keep" leaves user-data references alone after uninstall – useful when the value points to user-generated content you do not want to lose.
Reference an MSI property
{
"name": "MY_COMPANY_PRODUCT_CODE",
"value": "[ProductCode]"
}
[ProductCode] is resolved at install time by the MSI engine.
Suppressing env-var expansion
Sometimes you literally want a percent-delimited string in the name or value without expansion. Double the %:
{
"name": "%%LITERAL_NAME_NOT_EXPANDED%%",
"value": "%WILL_EXPAND%"
}
In the example above:
- The variable name is set to the literal string
%LITERAL_NAME_NOT_EXPANDED%. - The value is the runtime value of the
%WILL_EXPAND%env var on the build machine (because expansion happens at build).
For runtime expansion on the install machine, store an MSI Formatted token like [%MY_RUNTIME_VAR] instead. The MSI engine resolves [%environmentvariable] tokens at install time.
Action matrix – cheat sheet
| Goal | onInstall | onUninstall | valueAction |
|---|---|---|---|
| Create-or-overwrite a single variable, remove on uninstall | CreateOrUpdate | Remove | Replace |
Append to PATH, strip on uninstall | CreateOrUpdate | Remove | AppendEnd |
| Set only if not present, never touch on uninstall | Create | Keep | n/a (no change) |
| Force-remove an env var from the system | Remove | Remove | n/a |
Default
valueActionisAppendEnd– fine forPATH, but wrong for single-value variables like a home directory. Always setReplaceexplicitly when you mean it.
Notes:
- Re-installs don't double-append – Windows Installer checks for the existing segment before appending again.
- Uninstall cleanly removes only the appended segment, not the whole variable, when
onUninstall: "Remove"is paired with anAppend*action.
MSI vs MSIX behavior
| Aspect | MSI | MSIX |
|---|---|---|
| Real system env var | Yes (broadcasts WM_SETTINGCHANGE). | No – set inside the package container only. |
| Per-user vs per-machine | Honors msi.type. System variables require admin (elevated install). | Always per-package container (no system reach). |
Action semantics (onInstall, onUninstall, valueAction) | Honored. | Ignored. The MSIX manifest just declares the variable. |
| Visible to other apps after install | Yes, after a session restart or WM_SETTINGCHANGE. Open a new terminal to verify. | Only to processes running inside the MSIX container. |
Validation rules
| Validator | Catch |
|---|---|
required | name and value are mandatory. |
min | Neither may be empty. |
valid value (on msi.type, msi.onInstall, msi.onUninstall, msi.valueAction) | Must be one of the enum values listed above. |