fix: marshal MSI install properties into deferred CustomActionData

This commit is contained in:
2026-07-17 11:54:33 +01:00
parent 1ad5b5d6db
commit 2fe08ad7e9
+25 -3
View File
@@ -32,9 +32,31 @@
</Feature>
<!-- Write config.yaml, then install + start the service via nssm.
Implemented as sequenced CustomActions running a helper script. -->
<CustomAction Id="WriteConfig" Directory="INSTALLDIR"
ExeCommand='cmd.exe /c powershell -ExecutionPolicy Bypass -File "[INSTALLDIR]setup.ps1" -ServerId "[SERVERID]" -Token "[TOKEN]" -ServerUrl "[SERVERURL]" -InstallDir "[INSTALLDIR]"'
Implemented as sequenced CustomActions running a helper script.
Deferred CustomActions run out-of-process (and with Impersonate="no",
as SYSTEM) with NO access to the installer property table, so
"[SERVERID]"/"[TOKEN]"/"[SERVERURL]"/"[INSTALLDIR]" would resolve to
empty strings if referenced directly on the deferred action. The fix
is the standard CustomActionData marshaling pattern: an immediate
SetProperty (type 51) with the SAME Id as the deferred CustomAction
runs first (while property values are still visible) and resolves
the formatted string; the deferred Directory/ExeCommand CustomAction
that shares that Id then receives the resolved string back as its
CustomActionData, referenced here as "[WriteConfig]". This avoids
pulling in the WixToolset.Util extension (WixQuietExec64) purely to
get CustomActionData plumbing.
NOTE: this only builds/validates the MSI's XML in CI - it has not
been verified with a real install on Windows. Needs a smoke test
(msiexec /i, confirm C:\ProgramData\Vantage\config.yaml or similar
is written with the correct values, and the service starts) on an
actual Windows machine before this is trusted in production. -->
<SetProperty Id="WriteConfig"
Before="WriteConfig" Sequence="execute" Condition="NOT Installed"
Value='cmd.exe /c powershell -ExecutionPolicy Bypass -File "[INSTALLDIR]setup.ps1" -ServerId "[SERVERID]" -Token "[TOKEN]" -ServerUrl "[SERVERURL]" -InstallDir "[INSTALLDIR]"' />
<CustomAction Id="WriteConfig" Directory="INSTALLDIR" ExeCommand="[WriteConfig]"
Execute="deferred" Impersonate="no" Return="check" />
<InstallExecuteSequence>