Wix安装器忽略ALLUSERS参数问题及解决方案咨询
解决Wix安装器运行脚本时ALLUSERS参数失效问题
问题背景
用Wix制作了一个简易安装器,会将安装包和install.cmd脚本解压到C:\Windows\temp并自动执行脚本。但发现两种运行场景下安装路径不一致:
- 通过Wix安装器运行时,
INSTALL.log显示WixPerUserFolder为C:\windows\system32\config\systemprofile\AppData\Local\Apps\Remote Desktop - 直接在命令行运行
install.cmd时,路径则为C:\Users\Admin\AppData\Local\Apps\Remote Desktop
显然脚本中指定的ALLUSERS=1参数在Wix环境下没有生效,需要修复这个问题。
核心原因
问题出在Wix自定义动作的身份模拟设置:当前的CustomAction配置了Impersonate="no",这会让脚本以系统账户(SYSTEM)身份执行,而非当前登录的用户账户。系统账户的上下文环境和普通用户不同,即使脚本里指定了ALLUSERS=1,也会导致安装路径指向系统配置目录,而非用户个人目录。
解决方案
1. 修改自定义动作的身份模拟属性
将Wix配置中CustomAction的Impersonate="no"改为Impersonate="yes",这样脚本会以当前登录用户的身份运行,环境变量和用户上下文与手动执行脚本时一致,ALLUSERS=1参数就能正确生效。
修改后的CustomAction代码:
<CustomAction Id="RunWrapExe" Return="asyncNoWait" Execute="deferred" FileKey="File100" ExeCommand="" HideTarget="no" Impersonate="yes" />
注意:由于安装器设置了
InstallScope="perMachine",默认会请求管理员权限,Impersonate="yes"会让脚本在用户的高权限上下文下运行,保证安装权限足够。
2. 直接在Wix中调用msiexec(推荐)
跳过中间的install.cmd脚本,直接在Wix的自定义动作里调用msiexec并传递参数,减少中间环节的干扰,更可靠地控制安装行为。
替换原自定义动作和执行序列:
<!-- 新增直接调用msiexec的自定义动作 --> <CustomAction Id="RunMSI" Return="check" Execute="deferred" Impersonate="yes" ExeCommand='msiexec.exe ALLUSERS=1 /i "[WindowsFolder]Temp\RemoteDesktop_1.2.5255.0_x64.msi" /l* "[WindowsFolder]Temp\INSTALL.log" /quiet /norestart' /> <InstallExecuteSequence> <!-- 替换原来的RunWrapExe为新动作 --> <Custom Action="RunMSI" After="InstallFiles">NOT REMOVE~="ALL"</Custom> <PublishComponents Suppress="yes" /> <PublishFeatures Suppress="yes" /> <PublishProduct Suppress="yes" /> <RegisterProduct Suppress="yes" /> <RegisterUser Suppress="yes" /> </InstallExecuteSequence>
3. 检查脚本中的环境变量
脚本里设置了TMP和TEMP指向系统临时目录,但这不是路径异常的核心原因。不过可以检查SetVariables.cmd中是否有修改ALLUSERS或用户目录相关的逻辑,避免参数被意外覆盖。
附原代码
原AppInstaller.wxs
<?xml version='1.0'?> <Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'> <Product Id='*' UpgradeCode="3508345-7155-452D-879E-7AC8592FC9B6" Name='AppInstaller' Language='1033' Version='1.0.0.0' Manufacturer='ABC'> <Package Description='AppInstaller script' InstallerVersion='200' InstallScope="perMachine" Compressed='yes' /> <Property Id="AllUSERS" Value="1"/> <Media Id='1' Cabinet='setup.cab' EmbedCab='yes' /> <!-- Package components: define which files to be included in self-extracting package. --> <Directory Id='TARGETDIR' Name='SourceDir'> <Directory Id="WindowsFolder"> <Directory Id="INSTALLLOCATION" Name="Temp"> <Component Id='AppInstallerComponent' DiskId='1' Guid=''> <File Id="File0" Name="RemoteDesktop_1.2.5255.0_x64.msi" Source="Files\RemoteDesktop_1.2.5255.0_x64.msi" /> </Component> </Directory> </Directory> <Directory Id="TempFolder"> <Directory Id="tmpdir" Name="~_tmpdir"> <Component Id='AppInstallScript' DiskId='1' Guid=''> <File Id="File100" Name="install.cmd" Source="Files\install.cmd" /> </Component> </Directory> </Directory> </Directory> <Feature Id='InstallFeature' Title='Install Feature' Level='1'> <ComponentRef Id='AppInstallerComponent' /> <ComponentRef Id='AppInstallScript' /> </Feature> <!-- Run Action: define which file to run after the package is extracted --> <CustomAction Id="RunWrapExe" Return="asyncNoWait" Execute="deferred" FileKey="File100" ExeCommand="" HideTarget="no" Impersonate="no" /> <InstallExecuteSequence> <Custom Action="RunWrapExe" After="InstallFiles">NOT REMOVE~="ALL"</Custom> <PublishComponents Suppress="yes" /> <PublishFeatures Suppress="yes" /> <PublishProduct Suppress="yes" /> <RegisterProduct Suppress="yes" /> <RegisterUser Suppress="yes" /> </InstallExecuteSequence> </Product> </Wix>
原install.cmd
REM The following is required in all INSTALL.CMD files Call c:\system.sav\util\SetVariables.cmd Set block=%~dp0 Set TMP=C:\Windows\Temp Set TEMP=%TMP% REM Install Remote Desktop & capture logs start /wait msiexec.exe ALLUSERS=1 /i C:\Windows\Temp\RemoteDesktop_1.2.5255.0_x64.msi /l* C:\Windows\Temp\INSTALL.log /quiet /norestart REM if %ERRORLEVEL% equ 0 del /F /Q C:\Windows\Temp\RemoteDesktop_1.2.5255.0_x64.msi
内容的提问来源于stack exchange,提问作者Ming
相关产品推荐
相关产品推荐

