使用 WiX 为 InstallShield 安装程序创建 msi 包装器

Posted

技术标签:

【中文标题】使用 WiX 为 InstallShield 安装程序创建 msi 包装器【英文标题】:Create msi wrapper for InstallShield installer using WiX 【发布时间】:2013-07-31 11:52:42 【问题描述】:

我们使用 InstallShield 技术为客户准备了安装程序。安装程序工作正常,但客户希望此安装程序采用 msi 技术。我们决定使用 WiX 创建包装器。 Msi 安装程序应该做几件事:

    将 IS 安装程序解压到临时目录中。 运行 InstallShield setup.exe。 IS 完成后删除临时目录。

我们之前没有做过 WiX 技术的安装程序,这些是我们的问题:

    我们不知道如何使用 WiX 将目录及其所有文件(安装程序)嵌入到 msi 中。 我们不知道如何只运行 msi(它不应该安装数据,只在安装过程中运行嵌入的 IS setup.exe 并在之后删除)。 我们不知道如何在安装过程中运行 exe。

这是我目前创建的 *.wxs 文件:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Product Id="*" Name="ISSetupPackeger" Language="1033" Version="1.0.0.0" Manufacturer="MyCompany" UpgradeCode="8804d459-2ea5-4bbc-85f7-dfc8419cafe4">
        <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" Id="*" InstallPrivileges="elevated" />

        <!-- TODO setup.exe starts but we don't want to run it using cmd -->
        <CustomAction Id="LaunchInstaller" Directory="InstallerDir" ExeCommand="cmd /C setup.exe" Impersonate="yes" Return="ignore" />
        <InstallExecuteSequence>
            <Custom Action="LaunchInstaller" After="InstallFinalize" />
        </InstallExecuteSequence>

        <Media Id='1' Cabinet='data.cab' EmbedCab='yes'/>
            <Feature Id="ProductFeature" Title="WixInstallerProject" Level="1">
                <ComponentGroupRef Id="ProductComponents" />
            </Feature>

        <!-- TODO How to extract files to temp dir? Is there some TEMP constant? -->
        <Directory Id="TARGETDIR" Name="SourceDir" >
            <Directory Id="TempDir" Name="inst">
                <Directory Id="InstallerDir" Name="Installer"/>
            </Directory>
        </Directory>

        <!-- component group which will be installed into tempdir -->
        <ComponentGroup Id="ProductComponents" Directory="InstallerDir">
            <Component Id="Installer" Guid="7b8bd37f-7eda-4c3a-8155-9dae1a6bbf98">
                <!-- TODO How to embed directory with all its files/subdirectories? -->
                <File Id="_Setup.dll" Name="_Setup.dll" DiskId="1" Source="installer\_Setup.dll"/>
                <File Id="data1.cab" Name="data1.cab" DiskId="1" Source="installer\data1.cab"/>
                <File Id="data1.hdr" Name="data1.hdr" DiskId="1" Source="installer\data1.hdr"/>
                <File Id="data2.cab" Name="data2.cab" DiskId="1" Source="installer\data2.cab"/>
                <File Id="data2.hdr" Name="data2.hdr" DiskId="1" Source="installer\data2.hdr"/>
                <File Id="ISSetup.dll" Name="ISSetup.dll" DiskId="1" Source="installer\ISSetup.dll"/>
                <File Id="layout.bin" Name="layout.bin" DiskId="1" Source="installer\layout.bin"/>
                <File Id="setup.exe" Name="setup.exe" DiskId="1" Source="installer\setup.exe"/>
                <File Id="setup.ini" Name="setup.ini" DiskId="1" Source="installer\setup.ini"/>
            </Component>
        </ComponentGroup>

    </Product>

</Wix>

【问题讨论】:

【参考方案1】:

一些替代方案:

从文件来看,您使用 InstallShield 创建的安装程序似乎是 InstallScript 非 MSI 安装程序。您可能能够使用 InstallShield 转换器将其转换为 InstallScript MSI 安装程序。请参阅此问题和answer。

我阅读转换为 MSI 的要求与您不同。对于任何有价值的包装或转换,都应该利用 Windows Installer 管理实际安装的文件的安装。为此,如果转换不可行,您必须从头开始重写安装程序。您的方法只是将 MSI 用作捆绑包。你应该清楚你想做什么。

如果您应该选择捆绑路线,WiX 现在提供了一个名为 Burn 的引导程序/下载程序/链接程序/捆绑程序。有了它,您可以创建一个 .exe 来提取并运行您现有的安装程序。而且,如果需要,您可以创建一个 InstallShield 响应文件,以便可以静默运行现有安装。 (请参阅 InstallShield 文档。)

【讨论】:

我们不想创建 InstallShield MSI,因为在不久的将来我们希望将其更改为其他一些技术(可能是 WiX)。我们现在也不想从头开始写,因为我们没有足够的时间。我们要做的是创建 msi 包装器,它将提取 InstallShield 非 MSI 安装程序,运行它并在安装后删除其文件。 跳过复杂的自定义操作。只需编写一个应用程序,安装它和 InstallShield 设置文件,在安装结束时运行该应用程序(请参阅 WiX howto 文档)。它可以运行 InstallShield 安装程序,然后启动 msiexec 以删除自己的安装并在 Windows Installer 启动时快速退出。 如果您的安装程序的活动不太依赖于目标机器的特定状态,您也许可以通过“重新打包程序”构建 MSI。一些重新打包者通过观察安装程序所做的工作并创建一个 MSI 来模仿它。这是Flexera's 的信息。但是话又说回来,如果它足够简单,重写安装程序将是最有效和最可靠的途径。无论哪种方式都需要开发和测试时间。【参考方案2】:

您可以使用 WiX Bootstrapper 嵌入现有的 InstallShield 可执行文件。无需转换。

在我们的例子中,从 InstallShield 构建的 Setup.exe 实际上有一个 MSI。 (我认为通常是这种情况)。那么你有两个选择: - 您可以提取该 MSI(谷歌“从 InstallShield 提取 MSI”)并使用 MsiPackage 将其嵌入到引导程序中 - 或者您可以使用 ExePackage 嵌入整个 Setup.exe

向 MSI 传递参数:简单

<MsiPackage Id="bla" SourceFile="path-to-msi>
  <MsiProperty Name="PUBLIC_PROPERTY_IN_UPPERCASE" value="yourvalue"/>
</MsiPackage>

将参数传递给 InstallShield Setup.exe:棘手 在我们的例子中,Setup.exe 最终将参数传递给 MSI,请使用 /v"the-parameters-go-here-but-you-have-to-escape-properly" 听起来很简单,但正确转义斜杠 (\)、单引号 (')、双引号 (") 很复杂。此外,如果整个 InstallArgument 包含在 '(单引号)或 "(双引号)中,WiX 以不同方式转义 \引号)。我从单引号开始,因为它看起来更容易,但最终使用双引号。使用安装日志查看实际通过每一层的内容。

<Wix> 
  <Bundle>

  <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.HyperlinkLicense">
      <bal:WixStandardBootstrapperApplication
        xmlns:bal="http://schemas.microsoft.com/wix/BalExtension"
        LicenseUrl=""/>
  </BootstrapperApplicationRef>

  <!-- rumor has it Windows Installer needs the trailing slash for paths -->
  <Variable Name="InstallPath" Value="C:\path\to\destination\on\target\machine\" Type="string" bal:Overridable="yes"/>


  <Chain>  
    <MsiPackage Id="package_your_msi"
                SourceFile="path-to-msi"
                DisplayInternalUI="no"
                ForcePerMachine="yes"
                Compressed="yes"
                After="package_some_other_msi">
      <MsiProperty Name="TEST_PROPERTY_5" Value="5"/>
    </MsiPackage>      


    <ExePackage Id="package_installshield_setup_exe"
                SourceFile="C:\path\to\Setup.exe"
                Compressed="yes" 
                PerMachine="yes">
        <CommandLine InstallArgument="/s /v&quot;/qn INSTALLDIR=\&quot;[InstallPath] \&quot; HOST_ADDRESS=[HostAddress] HOST_PORT=[HostPort] SCANNER_MODEL=[ScannerType]&quot;"
                     Condition="use_registry_values=1 AND other_cond=1"/>
        </ExePackage>
  </Bundle>
</Wix>

来源:https://social.msdn.microsoft.com/Forums/windows/en-US/1a113abd-dca1-482b-ac91-ddb0dcc5465c/is-it-possible-to-pass-commandline-arguments-to-an-installshield-executable?forum=winformssetup

http://helpnet.installshield.com/installshield22helplib/helplibrary/IHelpSetup_EXECmdLine.htm

【讨论】:

以上是关于使用 WiX 为 InstallShield 安装程序创建 msi 包装器的主要内容,如果未能解决你的问题,请参考以下文章

Wix - 如何创建一个临时文件以在安装期间使用

确定先前软件包版本的 WiX 错误

如何在wix中将属性传递给回滚自定义操作?

在 WiX 中包含许多文件,但没有列出每个文件。

在 Bundle 或 MSI 中升级?

升级使用 installshield 创建的安装时,UAC 弹出红色