如何通过电子生成器参数化MSI文件

时间:2019-04-01 17:14:22

标签: windows-installer electron-builder

我正在尝试使用电子构建器(版本20.39.0)创建一个.msi安装程序文件,该文件可以在安装期间进行参数化。 参数(例如服务器端点)应写入文件中。

示例:
MsiExec /i "MyProject.msi" SERVER_ENDPOINT=myapp.example.com
那么myapp.example.com应该出现在安装目录中的文件中。

我尝试编辑electron-builder's wix template file,添加以下内容以将$ {SERVER_ENDPOINT}写入server.txt

文件C:\...\MyProject\node_modules\electron-builder-lib\templates\msi\template.xml

...
<CustomAction Id="writeConfigFile" Directory="APPLICATIONFOLDER" Execute="commit" Impersonate="yes" ExeCommand="cmd.exe /c &quot;echo ${SERVER_ENDPOINT} > server.txt&quot;" Return="check" />
...
<InstallExecuteSequence>
  ...
  <Custom Action="writeConfigFile" After="InstallFinalize"/>
</InstallExecuteSequence>

运行

MsiExec /i "MyProject.msi" /L*v Install.log SERVER_ENDPOINT=myapp.example.com

我还没工作。它会安装,但不会在日志文件中显示writeConfigFile

您认为这是使msi文件参数化的正确方法吗?
还是您会推荐其他解决方案?

我还找到了Orca.exe来创建MST文件,但是我希望有一个简单的解决方案,而无需手动操作。

3 个答案:

答案 0 :(得分:3)

设置MSI属性

我不熟悉Electron Builder。但是,以MSI术语来说,您需要指定文件中的内容应替换为MSI Property,然后需要在 transform 中设置属性,通过 command line 或在 property table 中(嵌入在MSI中)。

实际上,您可以一次设置所有三个,但我不确定哪个适用:-)。命令行当然会覆盖属性表,但是我不确定在转换和命令行参数之间的争斗中会赢得什么:

转换 (在命令行上应用转换,转换文件中的实际设置- mst ):

msiexec.exe /i "MySetup.msi" TRANSFORMS="MyTransform.mst"

命令行 (在命令行上设置PUBLIC属性):

msiexec.exe /i "MySetup.msi" MYPROPERTY="My Value here"

属性表 (每个MSI中的内置属性表也可以设置值):

Property Table


使用MSI属性

设置属性显然是不够的,您必须定义该值在安装过程中的位置。

  • 如果文件是 INI file ,则设置参数非常容易,因为这是MSI的内置功能。<​​/ li>
  • XML file updates text file updates 更为糟糕,因为这时您依赖第三方解决方案,或者自己通过自定义操作({{ 3}})。

I would not do the latter具有非常好的功能,可以替换XML和文本文件中的参数。 Advanced Installer也具有此类功能。开源Installshield也有WiX toolkit,但是它比商业工具要复杂得多。

关于电子,我不知道它是如何工作的。但是,无论哪种情况,中心任务都是使MSI包含这样的构造:

features to support XML file updates

这是使用Advanced Installer编译的MSI。您会看到我有一个参数化值[MYVALUE]。由于它是ALL UPPERCASE属性-也称为PUBLIC MSI属性,因此可以在命令行上进行设置。在安装过程中,括号中的属性将被传入的值替换。显然。


某些链接

答案 1 :(得分:0)

在SteinÅsmul的帮助下,这是我目前的解决方案:

我采用了当前的WiX template of electron-builder,并添加了一个将变量写入ini文件的选项。

<Property Id="MYSERVER" Value="notDefined"/>
<Property Id="MYSECONDPROPERTY" Value="notDefined"/>
...
<Directory Id="APPLICATIONFOLDER" Name="${installationDirectoryWixName}">
  <Component Id="AddLineTo_AppConfig.ini" Guid="{4171FB60-FDC5-46CF-A4D8-4AE9CADB4BE9}" KeyPath="yes" Feature="ProductFeature">
    <IniFile Id="AddLineTo_AppConfig.ini1" Name="AppConfig.ini" Directory="APPLICATIONFOLDER" Section="AppConfig" Key="Server" Value="&quot;[MYSERVER]&quot;" Action="addLine"/>
    <IniFile Id="AddLineTo_AppConfig.ini2" Name="AppConfig.ini" Directory="APPLICATIONFOLDER" Section="AppConfig" Key="SecondProp" Value="&quot;[MYSECONDPROPERTY]&quot;" Action="addLine"/>
  </Component>
</Directory>

完整的模板如下:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
  <!-- extended Template from https://github.com/electron-userland/electron-builder/blob/7f0ede7182ab6db8efb0cf4bf3cb183be712fb4e/packages/app-builder-lib/templates/msi/template.xml -->
  <!-- https://blogs.msdn.microsoft.com/gremlininthemachine/2006/12/05/msi-wix-and-unicode/ -->
  <Product Id="*" Name="${productName}" UpgradeCode="${upgradeCode}" Version="${version}" Language="1033" Codepage="65001" Manufacturer="${manufacturer}">
    <Package Compressed="yes" InstallerVersion="500"/>

    <Condition Message="Windows 7 and above is required"><![CDATA[Installed OR VersionNT >= 601]]></Condition>

    <!--
    AllowSameVersionUpgrades:
      When set to no (the default), installing a product with the same version and upgrade code (but different product code) is allowed and treated by MSI as two products.
      When set to yes, WiX sets the msidbUpgradeAttributesVersionMaxInclusive attribute, which tells MSI to treat a product with the same version as a major upgrade.

      So, AllowSameVersionUpgrades="yes" allows to build and test MSI with the same version, and previously installed app will be removed.
    -->
    <MajorUpgrade AllowSameVersionUpgrades="yes" DowngradeErrorMessage='A newer version of "[ProductName]" is already installed.'/>
    <MediaTemplate CompressionLevel="${compressionLevel}" EmbedCab="yes"/>

    <Property Id="ApplicationFolderName" Value="${installationDirectoryWixName}"/>
    <Property Id="WixAppFolder" Value="WixPerUserFolder"/>
    <Property Id="MYSERVER" Value="notDefined"/>
    <Property Id="MYSECONDPROPERTY" Value="notDefined"/>

    {{ if (iconPath) { }}
    <Icon Id="icon.ico" SourceFile="${iconPath}"/>
    <Property Id="ARPPRODUCTICON" Value="icon.ico"/>
    {{ } -}}

    {{ if (isAssisted || isRunAfterFinish) { }}
    <CustomAction Id="runAfterFinish" FileKey="mainExecutable" ExeCommand="" Execute="immediate" Impersonate="yes" Return="asyncNoWait"/>
    {{ } -}}

    <Property Id="ALLUSERS" Secure="yes" Value="2"/>
    {{ if (isPerMachine) { }}
    <Property Id="MSIINSTALLPERUSER" Secure="yes"/>
    {{ } else { }}
    <Property Id="MSIINSTALLPERUSER" Secure="yes" Value="1"/>
    {{ } -}}

    {{ if (isAssisted) { }}
    <!-- Check "Run after finish" checkbox by default -->
    <Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOX" Value="1"/>
    <Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="Run ${productName}"/>

    <UIRef Id="WixUI_Assisted"/>
    {{ } else if (isRunAfterFinish) { }}
    <!-- https://stackoverflow.com/questions/1871531/launch-after-install-with-no-ui -->
    <InstallExecuteSequence>
      <Custom Action="runAfterFinish" After="InstallFinalize"/>
    </InstallExecuteSequence>
    {{ } -}}

    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="${programFilesId}">
        <Directory Id="APPLICATIONFOLDER" Name="${installationDirectoryWixName}">
          <Component Id="AddLineTo_AppConfig.ini" Guid="{4171FB60-FDC5-46CF-A4D8-4AE9CADB4BE9}" KeyPath="yes" Feature="ProductFeature">
            <IniFile Id="AddLineTo_AppConfig.ini1" Name="AppConfig.ini" Directory="APPLICATIONFOLDER" Section="AppConfig" Key="Server" Value="&quot;[MYSERVER]&quot;" Action="addLine"/>
            <IniFile Id="AddLineTo_AppConfig.ini2" Name="AppConfig.ini" Directory="APPLICATIONFOLDER" Section="AppConfig" Key="SecondProp" Value="&quot;[MYSECONDPROPERTY]&quot;" Action="addLine"/>
          </Component>
        </Directory>
      </Directory>

      <!-- Desktop link -->
      {{ if (isCreateDesktopShortcut) { }}
      <Directory Id="DesktopFolder" Name="Desktop"/>
      {{ } -}}

      <!-- Start menu link -->
      {{ if (isCreateStartMenuShortcut) { }}
      <Directory Id="ProgramMenuFolder"/>
      {{ } }}
    </Directory>

    <!-- Files -->
    <Feature Id="ProductFeature" Absent="disallow">
      <ComponentGroupRef Id="ProductComponents"/>
    </Feature>

    {{-dirs}}

    <ComponentGroup Id="ProductComponents" Directory="APPLICATIONFOLDER">
      {{-files}}      
    </ComponentGroup>
  </Product>
</Wix>

我使用electronic-builder@20.39.0创建MSI,

set DEBUG=electron-builder:*
cp template.xml .\node_modules\app-builder-lib\templates\msi\template.xml
electron-builder

然后使用以下命令安装MSI

MsiExec /i "myapp.msi" MYSERVER=myapp.example.com MYSECONDPROPERTY=helloworld /L*v Install.log

安装完成后,我在安装目录(%USERPROFILE%\AppData\Local\Programs\MyApp\AppConfig.ini)中获得了AppConfig.ini

[AppConfig]
Server="myapp.example.com"
SecondProp="helloworld"

答案 2 :(得分:0)

最近的配置属性已添加到 22.11.x 和支持在将 project.wxs 编译为 MSI 之前对其进行修改的版本。

msiProjectCreated

它接受一个函数或一个函数字符串,并接受一个参数作为项目路径的参数。wxs

这应该能让您更好地利用扩展或根据安装时间属性创建自定义 ini 文件。