Skip to content

Commit c5143c8

Browse files
fix(msi): switch to Property-attribute custom actions (MSI Type 50)
WiX 4 silently strips [CustomActionData] tokens from ExeCommand at compile time, so Directory+ExeCommand based CAs end up with the args missing — binary gets invoked with just the exe path, no subcommand. Switching to the Property attribute (Type 50: exe-from-property) bypasses ExeCommand entirely: MSI reads the full command line directly from the property whose name matches the CA Id, auto-populated as CustomActionData at deferred execution time.
1 parent ea55aae commit c5143c8

2 files changed

Lines changed: 22 additions & 21 deletions

File tree

internal/buildinfo/version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package buildinfo
33
import "fmt"
44

55
const (
6-
Version = "1.11.2-msi-test4"
6+
Version = "1.11.2-msi-test5"
77
AgentURL = "https://github.com/step-security/dev-machine-guard"
88
)
99

packaging/windows/Product.wxs

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -99,64 +99,65 @@
9999
================================================================
100100
-->
101101

102-
<!-- ExeCommand uses [INSTALLFOLDER] (deferred-safe, MSI auto-passes
103-
it to deferred CAs) for the exe path, and [CustomActionData] for
104-
the args. WiX 4 strips a bare ExeCommand="[CustomActionData]"
105-
(treats it as an empty Target), so we MUST bake [INSTALLFOLDER]
106-
in literally — that keeps the column non-empty and lets MSI
107-
substitute both placeholders at deferred-execution time. -->
102+
<!-- Use the Property-attribute pattern (MSI Type 50: exe-from-property).
103+
Discovered the hard way that WiX 4 silently strips [CustomActionData]
104+
tokens out of ExeCommand at compile time, so Directory+ExeCommand
105+
CAs end up with empty (or args-less) Target columns. The Property
106+
pattern bypasses ExeCommand entirely: MSI reads the FULL command
107+
line (path + args) directly from a property whose name matches the
108+
CA's Id, which gets auto-populated as CustomActionData for the
109+
deferred execution. -->
108110

109111
<CustomAction Id="RunConfigureInline"
110-
Directory="INSTALLFOLDER"
111-
ExeCommand='"[INSTALLFOLDER]stepsecurity-dev-machine-guard.exe" [CustomActionData]'
112+
Property="RunConfigureInline"
112113
Execute="deferred"
113114
Impersonate="no"
114115
Return="check"/>
115116

116117
<CustomAction Id="RunConfigureFromFile"
117-
Directory="INSTALLFOLDER"
118-
ExeCommand='"[INSTALLFOLDER]stepsecurity-dev-machine-guard.exe" [CustomActionData]'
118+
Property="RunConfigureFromFile"
119119
Execute="deferred"
120120
Impersonate="no"
121121
Return="check"/>
122122

123123
<CustomAction Id="RunInstallScheduledTask"
124-
Directory="INSTALLFOLDER"
125-
ExeCommand='"[INSTALLFOLDER]stepsecurity-dev-machine-guard.exe" [CustomActionData]'
124+
Property="RunInstallScheduledTask"
126125
Execute="deferred"
127126
Impersonate="no"
128127
Return="check"/>
129128

130129
<CustomAction Id="RunUninstallScheduledTask"
131-
Directory="INSTALLFOLDER"
132-
ExeCommand='"[INSTALLFOLDER]stepsecurity-dev-machine-guard.exe" [CustomActionData]'
130+
Property="RunUninstallScheduledTask"
133131
Execute="deferred"
134132
Impersonate="no"
135133
Return="ignore"/>
136134

137-
<!-- SetProperty values now contain ONLY the args (not the exe path),
138-
which become [CustomActionData] for the matching deferred CA. -->
135+
<!-- SetProperty values now carry the FULL command line (exe path + args).
136+
[INSTALLFOLDER] and the per-tenant properties are substituted at
137+
immediate-phase execution time (when they ARE expandable), then
138+
the resulting string is shipped to the deferred CA via the matching
139+
property name. -->
139140

140141
<SetProperty Id="RunConfigureInline"
141-
Value='configure --non-interactive --customer-id "[CUSTOMERID]" --api-endpoint "[APIENDPOINT]" --api-key "[APIKEY]" --scan-frequency "[SCANFREQUENCY]"'
142+
Value='"[INSTALLFOLDER]stepsecurity-dev-machine-guard.exe" configure --non-interactive --customer-id "[CUSTOMERID]" --api-endpoint "[APIENDPOINT]" --api-key "[APIKEY]" --scan-frequency "[SCANFREQUENCY]"'
142143
Sequence="execute"
143144
Before="RunConfigureInline"
144145
Condition="APIKEY AND NOT BOOTSTRAPFILE AND NOT Installed"/>
145146

146147
<SetProperty Id="RunConfigureFromFile"
147-
Value='configure --non-interactive --from-file "[BOOTSTRAPFILE]"'
148+
Value='"[INSTALLFOLDER]stepsecurity-dev-machine-guard.exe" configure --non-interactive --from-file "[BOOTSTRAPFILE]"'
148149
Sequence="execute"
149150
Before="RunConfigureFromFile"
150151
Condition="BOOTSTRAPFILE AND NOT Installed"/>
151152

152153
<SetProperty Id="RunInstallScheduledTask"
153-
Value='install'
154+
Value='"[INSTALLFOLDER]stepsecurity-dev-machine-guard.exe" install'
154155
Sequence="execute"
155156
Before="RunInstallScheduledTask"
156157
Condition="NOT Installed"/>
157158

158159
<SetProperty Id="RunUninstallScheduledTask"
159-
Value='uninstall'
160+
Value='"[INSTALLFOLDER]stepsecurity-dev-machine-guard.exe" uninstall'
160161
Sequence="execute"
161162
Before="RunUninstallScheduledTask"
162163
Condition="REMOVE=&quot;ALL&quot;"/>

0 commit comments

Comments
 (0)