Reputation: 6516
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:
We haven't done installer in WiX technology before, those are our problems:
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
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"/qn INSTALLDIR=\"[InstallPath] \" HOST_ADDRESS=[HostAddress] HOST_PORT=[HostPort] SCANNER_MODEL=[ScannerType]""
Condition="use_registry_values=1 AND other_cond=1"/>
</ExePackage>
</Bundle>
</Wix>
http://helpnet.installshield.com/installshield22helplib/helplibrary/IHelpSetup_EXECmdLine.htm
Upvotes: 0
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