You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在MSI安装Electron应用时运行带命令行参数的PowerShell脚本

解决Wix Toolset中MSI传递参数并执行PowerShell脚本的问题

问题场景

需通过命令行给Electron应用的MSI安装包传入USERID和APIKEY参数,示例命令:

msiexec /i "C:\example\filepath\ExampleAppInstaller.msi" USERID="1234" APIKEY="5678" /quiet

要求MSI安装时运行PowerShell脚本,将参数保存到用户APPDATA目录的JSON文件中,供应用首次启动读取。但使用Wix Toolset 5.0.1+2f00cbe6配置自定义动作后无法成功执行。

现有代码

PowerShell脚本(writeParams.ps1)

param(
    [string]$UserID,
    [string]$ApiKey
)

# 动态定义文件夹和文件路径
$AppDataFolder = "$env:APPDATA\ExampleAppTest"
$filePath = "$AppDataFolder\installParams.json"

# 检查文件夹是否存在,不存在则创建
if (-not (Test-Path -Path $AppDataFolder)) {
    New-Item -Path $AppDataFolder -ItemType Directory
}

# 创建包含参数的JSON内容
$jsonContent = @{
    userId = $UserID
    apiKey = $ApiKey
} | ConvertTo-Json

# 将JSON写入文件
$jsonContent | Out-File -FilePath $filePath

# 退出并返回成功码
exit 0

Wix项目文件(ExampleAppProject.wixproj)

<Project Sdk="WixToolset.Sdk/5.0.1">

  <PropertyGroup>
    <OutputType>Package</OutputType>
    <WixOutputName>ExampleAppInstaller</WixOutputName>
    <WixOutputType>MSI</WixOutputType>
  </PropertyGroup>

  <ItemGroup>
    <WixSource Include="Product.wxs" />
  </ItemGroup>

</Project>

Product.wxs文件

<?xml version="1.0"?>
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">

  <!-- 产品信息 -->
  <Product Id="*" Name="ExampleApp" Language="1033" Version="1.0.0.0" Manufacturer="Example" UpgradeCode="86a341fc-f2ff-4fc6-9627-8127bb1efc68">
    <Package InstallerVersion="500" Compressed="yes" InstallScope="perMachine" />

    <!-- 媒体元素定义cab文件 -->
    <Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />

    <!-- 目录定义安装路径 -->
    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="ProgramFilesFolder">
        <Directory Id="INSTALLFOLDER" Name="ExampleApp"/>
      </Directory>
    </Directory>

    <!-- 功能定义安装内容 -->
    <Feature Id="DefaultFeature" Level="1">
      <ComponentGroupRef Id="ProductComponents"/>
    </Feature>
  </Product>

  <!-- 定义要安装的文件 -->
  <Fragment>
    <DirectoryRef Id="INSTALLFOLDER">
      <Component Id="PowerShellComponent" Guid="1e20057b-3f79-4258-b054-27767beb202c">
        <File Id="PowerShellScript" Source="writeParams.ps1" KeyPath="yes"/>
      </Component>
    </DirectoryRef>
  </Fragment>

  <!-- 组件组 -->
  <Fragment>
    <ComponentGroup Id="ProductComponents">
      <ComponentRef Id="PowerShellComponent"/>
    </ComponentGroup>
  </Fragment>

  <!-- 定义执行PowerShell脚本的自定义动作 -->
  <Fragment>
    <CustomAction Id="RunPowerShellScript"
                  Property="powershell.exe"
                  ExeCommand="-ExecutionPolicy Bypass -File &quot;[INSTALLFOLDER]writeParams.ps1&quot; -UserID [USERID] -ApiKey [APIKEY]"
                  Execute="deferred"
                  Return="check"
                  Impersonate="no"/>

    <!-- 在安装文件复制后运行自定义动作 -->
    <InstallExecuteSequence>
      <Custom Action="RunPowerShellScript" After="InstallFiles">NOT Installed</Custom>
    </InstallExecuteSequence>
  </Fragment>

</Wix>

问题原因及修复步骤

核心问题

  1. 未声明公共属性:传入的USERID和APIKEY未在Wix中定义为公共属性,MSI会忽略外部传入的未声明参数。
  2. 延迟动作无法访问即时属性:延迟执行的自定义动作默认无法直接读取USERID这类即时属性,需要通过SetProperty动作传递参数。
  3. 权限与路径问题:设置Impersonate="no"后,脚本以系统权限运行,$env:APPDATA指向系统账户目录,而非当前用户目录。

修复后的Product.wxs关键改动

1. 声明公共属性

在<Product>节点内添加:

<Property Id="USERID" Secure="yes" />
<Property Id="APIKEY" Secure="yes" />

Secure="yes"确保属性可在延迟动作中访问。

2. 添加参数传递动作

创建即时的SetProperty动作,将参数存入延迟动作的上下文:

<CustomAction Id="SetScriptParams"
              Property="RunPowerShellScript"
              Value="-ExecutionPolicy Bypass -File &quot;[INSTALLFOLDER]writeParams.ps1&quot; -UserID [USERID] -ApiKey [APIKEY]"
              Execute="immediate"/>

3. 调整自定义动作配置

修改原延迟动作的ExeCommand为空,参数通过SetProperty传递,并开启用户模拟:

<CustomAction Id="RunPowerShellScript"
              Property="powershell.exe"
              ExeCommand=""
              Execute="deferred"
              Return="check"
              Impersonate="yes"/>

4. 调整执行顺序

确保先执行参数设置动作,再执行脚本:

<InstallExecuteSequence>
  <Custom Action="SetScriptParams" Before="RunPowerShellScript">NOT Installed</Custom>
  <Custom Action="RunPowerShellScript" After="InstallFiles">NOT Installed</Custom>
</InstallExecuteSequence>

完整修复后的Product.wxs

<?xml version="1.0"?>
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">

  <Product Id="*" Name="ExampleApp" Language="1033" Version="1.0.0.0" Manufacturer="Example" UpgradeCode="86a341fc-f2ff-4fc6-9627-8127bb1efc68">
    <Package InstallerVersion="500" Compressed="yes" InstallScope="perMachine" />

    <!-- 声明公共属性,允许外部传入并在延迟动作中访问 -->
    <Property Id="USERID" Secure="yes" />
    <Property Id="APIKEY" Secure="yes" />

    <Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />

    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="ProgramFilesFolder">
        <Directory Id="INSTALLFOLDER" Name="ExampleApp"/>
      </Directory>
    </Directory>

    <Feature Id="DefaultFeature" Level="1">
      <ComponentGroupRef Id="ProductComponents"/>
    </Feature>
  </Product>

  <Fragment>
    <DirectoryRef Id="INSTALLFOLDER">
      <Component Id="PowerShellComponent" Guid="1e20057b-3f79-4258-b054-27767beb202c">
        <File Id="PowerShellScript" Source="writeParams.ps1" KeyPath="yes"/>
      </Component>
    </DirectoryRef>
  </Fragment>

  <Fragment>
    <ComponentGroup Id="ProductComponents">
      <ComponentRef Id="PowerShellComponent"/>
    </ComponentGroup>
  </Fragment>

  <Fragment>
    <!-- 即时动作:设置延迟动作的参数 -->
    <CustomAction Id="SetScriptParams"
                  Property="RunPowerShellScript"
                  Value="-ExecutionPolicy Bypass -File &quot;[INSTALLFOLDER]writeParams.ps1&quot; -UserID [USERID] -ApiKey [APIKEY]"
                  Execute="immediate"/>

    <!-- 延迟动作:执行PowerShell脚本 -->
    <CustomAction Id="RunPowerShellScript"
                  Property="powershell.exe"
                  ExeCommand=""
                  Execute="deferred"
                  Return="check"
                  Impersonate="yes"/>

    <InstallExecuteSequence>
      <Custom Action="SetScriptParams" Before="RunPowerShellScript">NOT Installed</Custom>
      <Custom Action="RunPowerShellScript" After="InstallFiles">NOT Installed</Custom>
    </InstallExecuteSequence>
  </Fragment>

</Wix>

调试建议

  • 启用MSI日志:运行安装命令时添加/L*V "install.log"参数,查看日志中自定义动作的执行细节和错误信息。
  • 单独测试脚本:手动运行powershell.exe -ExecutionPolicy Bypass -File writeParams.ps1 -UserID 1234 -ApiKey 5678,确认脚本本身功能正常。

内容的提问来源于stack exchange,提问作者Benson Craft

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 04:48:11