I want to install microsoft visual c++ 2008 redistributable package along with my msi installer. I decide to include it along with my installer as an application file and i wrote a golang code that triggers the silent installation of microsoft visual c++ 2008 redistributable package. The Service of my application starts only when microsoft visual c++ 2008 redistributable package is installed. I could see a uninstall option for my application in the Control panel but i couldnt see anything like that for the microsoft visual c++ 2008 redistributable package. And i am pretty sure that the package is not installed because my application never starts, when i trigger the silent.exe (as an administrator) alone which has the code to silently install the package it gets installed and my application works fine as well. The problem occurs when i try to pack everything in a single msi.
The WiX Source file i wrote to include the silent.exe and also other necessary files i need for my application.
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:util='http://schemas.microsoft.com/wix/UtilExtension'>
<?include "CommonVariable.wxi"?>
<Product Id="*" Language="1033" Manufacturer="Testing" Name="Testing_Name" Version="1.1.1">
<Package InstallerVersion="111" Compressed="yes" Description = "(x64 Edition) MSI Package" Comments="(x64 Edition) MSI Package" InstallPrivileges="elevated" Platform="x64"/>
<Media Id="1" Cabinet="product.cab" EmbedCab="yes"/>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="MYINSTALLLOCATION" Name="$(var.foldername)">
<!-- Component for list of files to add in Installation location -->
<Component Id="ApplicationFiles" Guid="{**********-*******-*******-********}">
<File Id="ApplicationFile" Source="silent.exe" Vital="no" DiskId="1" Hidden="yes"/>
<File Id="ApplicationFile1" Source="Windows2008R2.exe" Vital="no" DiskId="1" Hidden="yes"/>
<File Id="ApplicationFile1" Source="Myfiles" Vital="no" DiskId="1" />
<File Id="ApplicationFile1" Source="Myfiles" Vital="no" DiskId="1" />
</Component>
***other Actions for my Application***
</Directory>
</Directory>
</Directory>
<DirectoryRef Id="MYINSTALLLOCATION">
<Component Id="CleanupMainApplicationFolder" Guid="{**********-*******-*******-********}" Win64="yes">
<util:RemoveFolderEx On="uninstall" Property="MYINSTALLLOCATION" />
</Component>
</DirectoryRef>
<Property Id="MYINSTALLLOCATION" Value="$(var.InstallationLocation)" >
</Property>
<Feature Id="DefaultFeature" Level="1">
<ComponentRef Id="ApplicationFiles"/>
</Feature>
<Binary Id="ExeId" SourceFile="silent.exe"/>
<CustomAction Id="SilentAction" BinaryKey="ExeId" ExeCommand="" Execute='deferred' Return ='asyncWait' Impersonate='no'/>
<InstallExecuteSequence>
<Custom Action='SilentAction' Before='InstallFinalize'/>
</InstallExecuteSequence>
</Product>
</Wix>
The Silent.exe is the golang code i wrote has many functions the part of the code i wrote to silently install the package is as below.
package main
import (
"fmt"
"os/exec"
)
func main() {
/*........................
...........................
..........................*/
/*The code above is for my Different purpose */
co := exec.Command("C:\\Windows2008R2.exe","/q","/c:\"msiexec","/i","Windows2008R2.msi","/qn","/l*v","C:\\Windows2008R2_x64.log\"")
if err := co.Run(); err != nil {
fmt.Println("Error: ", err)
}
}
Windows does not allow you to install an application when another application is being installed.So better you can have a MSI for that redistributable package and invoke it separately after the previous installation is done through wmic remote command.
Related
I am trying to build an installer with Wix 3.11.2 in Visual Studio 2019. I have the extension installed and the toolkit.
I want to use the XmlFile tag in the util namespace to modify the app.config of my installed application.
I have added a reference to C:\Program Files (x86)\WiX Toolset v3.11\bin\WixUtilExtension to the installer project.
I have added the util namespace to the Product.wxs
The xmlnamespace is recognized since I get intellisense etc.
However when building I get the error error CNDL0005: The Fragment element contains an unexpected child element 'util:XmlFile'
This is my Product.wxs:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Product Id="DBDA892E-D414-44E9-9F5E-49DCD25E209B" Name="TestWixError" Language="1033" Version="1.0.0.0" Manufacturer="Test" UpgradeCode="41e16593-71c1-4516-8ec3-bc8f4911e3f1">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate />
<Feature Id="ProductFeature" Title="TestWixErrorSetup" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="TestWixErrorSetup" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="MainExecutable" Guid="EA05AA88-F299-4EC2-A64A-4ADAB863C4AC">
<File Id="MainExecutable" Source="$(var.TestWixError.TargetPath)"/>
</Component>
<Component Id="MainPdb" Guid="8ACB76F7-BB83-4EA6-9F58-12CD015E88EC">
<File Source="$(var.TestWixError.TargetDir)$(var.TestWixError.TargetName).pdb" />
</Component>
<Component Id="MainConfig" Guid="39BAFF61-BA1A-42C3-9290-67019F6A6257">
<File Source="$(var.TestWixError.TargetPath).config" />
</Component>
</ComponentGroup>
</Fragment>
<Fragment>
<Property Id="HELLO" Value="Hello from install"/>
<util:XmlFile
Id="UpdateHello"
Action="setValue"
File="$(var.TestWixError.TargetPath).config"
SelectionLanguage="XPath"
Permanent="yes"
ElementPath="/configuration/appSettings/add[\[]#key='Hello'[\] ]/#value"
Value="[HELLO]" />
</Fragment>
</Wix>
The visual studio project is just a .net 4.7.1 console app that displays the value from Hello from the appsettings on the console.
The WixUtilExtension.dll is included in the call to candle.exe as you can see in this commandline (some parts redacted):
C:\Program Files (x86)\WiX Toolset v3.11\bin\candle.exe -dDebug -d"DevEnvDir=C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\IDE\\" -d"SolutionDir=C:\Users\---\Documents\Projecten\---\TestWixError\\" -dSolutionExt=.sln -dSolutionFileName=TestWixError.sln -dSolutionName=TestWixError -d"SolutionPath=C:\Users\---\Documents\Projecten\---\TestWixError\TestWixError.sln" -dConfiguration=Debug -dOutDir=bin\Debug\ -dPlatform=x86 -d"ProjectDir=C:\Users\---\Documents\Projecten\---\TestWixError\TestWixErrorSetup\\" -dProjectExt=.wixproj -dProjectFileName=TestWixErrorSetup.wixproj -dProjectName=TestWixErrorSetup -d"ProjectPath=C:\Users\---\Documents\Projecten\---\TestWixError\TestWixErrorSetup\TestWixErrorSetup.wixproj" -d"TargetDir=C:\Users\---\Documents\Projecten\---\TestWixError\TestWixErrorSetup\bin\Debug\\" -dTargetExt=.msi -dTargetFileName=TestWixErrorSetup.msi -dTargetName=TestWixErrorSetup -d"TargetPath=C:\Users\---\Documents\Projecten\---\TestWixError\TestWixErrorSetup\bin\Debug\TestWixErrorSetup.msi" -dTestWixError.Configuration=Debug -d"TestWixError.FullConfiguration=Debug|AnyCPU" -dTestWixError.Platform=AnyCPU -d"TestWixError.ProjectDir=C:\Users\---\Documents\Projecten\---\TestWixError\TestWixError\\" -dTestWixError.ProjectExt=.csproj -dTestWixError.ProjectFileName=TestWixError.csproj -dTestWixError.ProjectName=TestWixError -d"TestWixError.ProjectPath=C:\Users\---\Documents\Projecten\---\TestWixError\TestWixError\TestWixError.csproj" -d"TestWixError.TargetDir=C:\Users\---\Documents\Projecten\---\TestWixError\TestWixError\bin\Debug\\" -dTestWixError.TargetExt=.exe -dTestWixError.TargetFileName=TestWixError.exe -dTestWixError.TargetName=TestWixError -d"TestWixError.TargetPath=C:\Users\---\Documents\Projecten\---\TestWixError\TestWixError\bin\Debug\TestWixError.exe" -out obj\Debug\ -arch x86 -ext "C:\Program Files (x86)\WiX Toolset v3.11\bin\\WixUtilExtension.dll" Product.wxs
Things I have tried so far:
Removing the reference, restarting visual studio re-adding the reference
Moving the WixUtilExtension.dll to c:\temp\bin (with all other wix binaries included) and referencing from there.
Moving the WixUtilExtension.dll to the same location as the Product.wxs and referencing from there.
Looking at the WixUtilExtension.dll with ILSpy to verify that it contains a reference to the http://schemas.microsoft.com/wix/UtilExtension namespace (it does in resources it contains an xsd with this namespace)
Any suggestions to get this working are welcome.
Ok,
I am here to answer my own question, hopefully to help someone else in the future.
The util:XmlFile tag needs to be inside a Component tag.
So the fixed fragment looks like this:
<Fragment>
<Property Id="HELLO" Value="Hello from install"/>
<Component Id="TestConfigComponent" Directory="INSTALLFOLDER">
<util:XmlFile
Id="UpdateHello"
Action="setValue"
File="$(var.TestWixError.TargetPath).config"
SelectionLanguage="XPath"
Permanent="yes"
ElementPath="/configuration/appSettings/add[\[]#key='Hello'[\] ]/#value"
Value="[HELLO]" />
</Component>
</Fragment>
my idea is make an uninstall file with .msi install file. I read some information about creating uninstaller shortcut here: http://wixtoolset.org/documentation/manual/v3/howtos/files_and_registry/create_uninstall_shortcut.html , But i cant found information about make uninstall file after msi build , maybe whom know it's possible ? and if possible how i can do it ? or maybe it possible to do with cmd script? Just write script for automatically uninstall my program from mashine. My code is :
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"><?define WpfApp1_TargetDir=$(var.WpfApp1.TargetDir)?>
<Product Id="*" Name="SetupProject2" Language="1033" Version="1.0.0.0" Manufacturer="Andrejka" UpgradeCode="PUT-GUID-HERE">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<Property Id="WIXUI_INSTALLDIR" Value="TESTFILEPRODUCTDIR" />
<Property Id="WixShellExecTarget" Value="[#WpfApp1.exe]" />
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />
<Property Id="LAUNCH_APP_ON_EXIT" Value="1" />
<InstallExecuteSequence>
<Custom Action='LaunchApplication' After='InstallFiles'/>
</InstallExecuteSequence>
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOX" Value="1" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes"/>
<Feature Id="ProductFeature" Title="SetupProject2" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="TESTFILEPRODUCTDIR" Name="SetupProject2">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="SetupProject2" />
</Directory>
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<!-- TODO: Remove the comments around this Component element and the ComponentRef below in order to add resources to this installer. -->
<!-- <Component Id="ProductComponent"> -->
<!-- TODO: Insert files, registry keys, and other resources here. -->
<!-- </Component> -->
<Component Id="WpfApp1.exe" Guid="*">
<File Id="WpfApp1.exe" Name="WpfApp1.exe" Source="$(var.WpfApp1_TargetDir)WpfApp1.exe" />
</Component>
<Component Id="WpfApp1.exe.config" Guid="*">
<File Id="WpfApp1.exe.config" Name="WpfApp1.exe.config" Source="$(var.WpfApp1_TargetDir)WpfApp1.exe.config" />
</Component>
<Component Id="aws_sdk_net_core_support.dll" Guid="*">
<File Id="aws_sdk_net_core_support.dll" Name="aws-sdk-net-core-support.dll" Source="$(var.WpfApp1_TargetDir)aws-sdk-net-core-support.dll" />
</Component>
<Component Id="AWSSDK.Core.dll" Guid="*">
<File Id="AWSSDK.Core.dll" Name="AWSSDK.Core.dll" Source="$(var.WpfApp1_TargetDir)AWSSDK.Core.dll" />
</Component>
<Component Id="AWSSDK.SimpleNotificationService.dll" Guid="*">
<File Id="AWSSDK.SimpleNotificationService.dll" Name="AWSSDK.SimpleNotificationService.dll" Source="$(var.WpfApp1_TargetDir)AWSSDK.SimpleNotificationService.dll" />
</Component>
<Component Id="MimeSharp.dll" Guid="*">
<File Id="MimeSharp.dll" Name="MimeSharp.dll" Source="$(var.WpfApp1_TargetDir)MimeSharp.dll" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>
In general you are not supposed to put uninstall shortcuts in the start menu, it is in fact a violation of Microsoft's logo requirements for Windows applications I believe. Rather you should let people uninstall your product the normal way via the add/remove programs applet.
UPDATE: I found this answer with some more information on this topic: Shortcuts with name "Uninstall <Program Name>" are not displayed in Windows 8/8.1/10
Also, just so it is clear, uninstall, is a built-in feature of MSI files - it is always automatically available unless actively blocked (such as some applications hiding themselves from display in add/remove programs). There is nothing extra you have to do in your WiX sources to support uninstall properly. Just follow Windows Installer guidelines and it comes "for free".
If what you are asking is for a way to create an uninstall batch file, then you can find a plethora of ways to uninstall your MSI file in this "uninstall reference": Uninstalling an MSI file from the command line without using msiexec.
In short, just run the command line below to uninstall your MSI if you have the MSI's product code (you can find your product code by querying your system as described here: How can I find the product GUID of an installed MSI setup? - you might need to look it up since you auto-generate your product code):
msiexec.exe /x {your-product-guid}
or just uninstall by referring to your original MSI installation file like this:
msiexec.exe /x "c:\filename.msi
See the linked answer above (the uninstall reference) for a lot more information about this.
I am trying to create an installer for a simple .NET WPF C# app. I am using VS 2013, and WiX 3.10.2. Following the steps in the Wix Tutotial/ .NET/ Bootstrapping I have created a Boostrap.exe which chains .NET web installer and the app Setup.msi.
EDIT: My goal is to understand how to configure the WiX Bootstrap and Setup projects for small updates, minor upgrades, and major upgrades scenarios.
Out of the box, everything seems to work nice when I run a fresh install. However, when I run a fresh built Bootstrap.exe over an already existing installation a duplicate entry appears in the Apps & features and no file is changed in the app target location - contrary to the expectation that the same entry should remain in the Apps & features and the target location should be updated. EDIT: Looks like there may not be a way to change REINSTALLMODE?
If I add a Product Id and then change the version of the Setup (minor upgrade), the Bootstrap fails with User cancelled installation? The log file shows "Error 0x80070642: Failed to perform minor upgrade of MSI package." EDIT: Inside the MSI log a SecureRepair fails with error code 39439E438 (?) probably because the stored hash value does not match the current... but that should be expected in a minor upgrade MSI, right?
Are there recommended configurations between the Boostrapper and Setup WiX projects such that the small update, minor upgrade, and major upgrade use cases can be handled properly, or does the WiX Bootstrapper support ONLY major upgrades?
I will continue to investigate and I'll post updates to my findings;
Any hints are greatly appreciated,
Thanks!
Here are the source files which I barely changed from the WiX wizard generated code:
--- Product.wxs ---
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="SetupProject1 1.0.0.0" Language="1033" Version="1.0.0.0" Manufacturer="Acme" UpgradeCode="4c8a8cbf-e3d0-410c-8a8d-7e67eb4e7ff7">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perUser" InstallPrivileges="limited" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate />
<Feature Id="ProductFeature" Title="SetupProject1" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="LocalAppDataFolder">
<Directory Id="AcmeFolder" Name="Acme">
<Directory Id="INSTALLFOLDER" Name="WpfApplication1" />
</Directory>
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="ProductComponent" Guid="8CA0B70F-39DA-4B4B-9104-46C58E26FCF4">
<CreateFolder/>
<RemoveFolder Id="RemoveAcmeFolder" Directory="AcmeFolder" On="uninstall"/>
<RemoveFolder Id="RemoveINSTALLFOLDER" On="uninstall" />
<RegistryValue Root="HKCU" Key="Software\Acme\WpfApplication1" Name="Version" Type="string" Value="[ProductVersion]" KeyPath="yes" />
<File Source="$(var.WpfApplication1.TargetPath)" KeyPath="no" />
</Component>
</ComponentGroup>
</Fragment>
--- Bundle.wxs ---
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
<Bundle Name="Bootstrapper1 1.0.0.0" Version="1.0.0.0" Manufacturer="Acme" UpgradeCode="e1092cbb-9134-42fc-a9f2-652f95f361fd">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense" />
<Chain>
<MsiPackage Name="Acme Setup" SourceFile="$(var.SetupProject1.TargetPath)" Vital="yes" />
</Chain>
</Bundle>
If you change your executables, increase their version numbers. Windows Installer assumes files with the same versions are the same.
To upgrade an .msi package, increase its version number either as part of a major upgrade (typical) or minor upgrade.
To upgrade a bundle, increase its version number. By default, Burn keeps bundles with the same version installed.
I am trying to create a WiX installer for a plugin of one of my applications but have come across something I find strange; perhaps it is the expected behavior but then I would like to know why.
My application saves its installation path in the following registry location:
HKEY_CURRENT_USER\SOFTWARE\MyCompany\MyApp\Installed
As default my application is installed to C:\Program Files\MyApp if x64 and C:\Program Files (x86)\MyApp if x86.
In my plugin installer I have the following in Product.wxs to retrieve the install path of my application:
<Property Id="MY_APP_DIR">
<RegistrySearch Id='my_app_dir' Type='raw' Root='HKCU' Key='SOFTWARE\MyCompany\MyApp' Name='Installed' />
</Property>
I then added the following just to see what is actually retrieved when I run the installer:
<Condition Message="[MY_APP_DIR]">
0
</Condition>
In the case where "C:\Program Files\MyApp\" is stored in the registry I got the following when I run the plugin installer:
Plugin installer (x86): C:\Program Files (x86)\MyApp\
Plugin installer (x64): C:\Program Files\MyApp\
Why is not the value stored in the registry retrieved independently of which platform the msi was built for?
On a x64 machine only the x64 versions of my installers will be used so this should not cause any problems it just confuses me.
EDIT: As requested I have included my entire Product.wxs:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="TestInstaller" Language="1033" Version="1.0.0.0" Manufacturer="MyCompany" UpgradeCode="SOME_GUID">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes" />
<Property Id="MY_APP_DIR">
<RegistrySearch Id="my_app_dir" Root="HKCU" Key="SOFTWARE\MyCompany\MyApp" Name="Installed" Type="raw" />
</Property>
<Condition Message="[MY_APP_DIR]">
0
</Condition>
<Feature Id="ProductFeature" Title="TestInstaller" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="INSTALLFOLDER" Name="TestInstaller">
<Directory Id="MY_APP_DIR" Name="MyAppInstallPath">
<Directory Id="MyAppBinFolder" Name="bin" />
</Directory>
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents">
<Component Id="ProductComponent" Guid="SOME_GUID" Directory="MyAppBinFolder">
<File Id="Foo.Bar" Source="Foo.Bar" KeyPath="yes" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>
Windows Installer has a rule called WIN64DUALFOLDERS which does not allow 32 bit installers to write to 64 bit locations. If you run your 32 bit installer on a 64 bit computer with diagnostic logging enabled you should see a section in the log file like this:
AppSearch: Property: MY_APP_DIR, Signature: my_app_dir
MSI (c) (BC:F4) [10:00:47:953]: Note: 1: 2262 2: Signature 3: -2147287038
MSI (c) (BC:F4) [10:00:47:953]: WIN64DUALFOLDERS: 'C:\Program Files (x86)\' will substitute 17 characters in 'C:\Program Files\MyCompany\MyApp' folder path. (mask argument = 0, the folder pair's iSwapAttrib member = 0).
MSI (c) (BC:F4) [10:00:47:953]: PROPERTY CHANGE: Adding MY_APP_DIR property. Its value is 'C:\Program Files (x86)\MyCompany\MyApp'.
Action ended 10:00:47: AppSearch. Return value 1.
Even though the path in the registry is C:\Program Files\, Windows Installer automatically redirects it to C:\Program Files (x86)\.
For more information see Disable WIN64DUALFOLDERS substitution in WIX.
Note: I deleted my previous answer because with the benefit of hindsight it wasn't useful.
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:
Extract IS installer into temp directory.
Run InstallShield setup.exe.
Remove temporary directory after IS finish.
We haven't done installer in WiX technology before, those are our problems:
We don't know how to embed directory with all it's files (installer) into msi using WiX.
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).
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>
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.)
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>
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