pepuch
pepuch

Reputation: 6516

Create msi wrapper for InstallShield installer using WiX

We've prepared installer for our client using InstallShield technology. Installer works fine but client wants this installer in msi technology. We decided to create wrapper using WiX. Msi installer should do few things:

  1. Extract IS installer into temp directory.
  2. Run InstallShield setup.exe.
  3. Remove temporary directory after IS finish.

We haven't done installer in WiX technology before, those are our problems:

  1. We don't know how to embed directory with all it's files (installer) into msi using WiX.
  2. We don't know how to ONLY run msi (it shouldn't install data, only run embeded IS setup.exe during installation and remove after).
  3. We don't know how to run exe during installation.

This is *.wxs file which I've created so far:

<?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>

Upvotes: 2

Views: 2486

Answers (2)

TomEberhard
TomEberhard

Reputation: 1091

You can use a WiX Bootstrapper to embed your existing InstallShield executable. No conversion needed.

In our case the Setup.exe as built from InstallShield actually has an MSI inside. (I think this is usually the case). So then you have two options:
- you can either extract that MSI (google "extract MSI from InstallShield") and embedded it in the bootstapper using MsiPackage
- or you can embed the whole Setup.exe, using ExePackage

Passing Parameters to an MSI: easy

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

Passing parameters to an InstallShield Setup.exe: tricky
In our case Setup.exe ends up passing the parameters to the MSI anyway, use /v"the-parameters-go-here-but-you-have-to-escape-properly"
Sounds easy, but it was complicated to properly escape slashes (\), single-quotes ('), double quotes ("). Also, WiX escapes \ differently if the whole InstallArgument is enclosed in ' (single quotes) or " (double quotes). I started with single quotes because it looked easier, but ended up using double quotes. Use the install log to see what gets actually passed through each layer.

<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>

Sources:
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

Upvotes: 0

Tom Blodget
Tom Blodget

Reputation: 20782

Some alternatives:

From the files, it looks like the installer you have created with InstallShield is an InstallScript non-MSI installer. You might be able to convert it to an InstallScript MSI installer with an InstallShield converter. See this question and answer.

I read the requirement to convert to MSI differently than you do. For any kind of wrapping or converting to be worthwhile, it should take advantage of Windows Installer managing the installation of the files that are actually installed. To do that, you'd have to rewrite the installer from scratch if a conversion is not feasible. Your approach simply uses an MSI as a bundle. You should get clarification on what you want to do.

If you due go with the bundling route, WiX now offers a bootstrapper/downloader/chainer/bundler called Burn. With it, you can create a single .exe that will extract and run your existing installer. And, if you want, you can create an InstallShield response file so the existing install can be run silently. (See the InstallShield documentation for that.)

Upvotes: 1

Related Questions