How to bundle 6 msi into one msi installer - wix

I have 6 msi that I want to bundle into single msi package. These 6 are office addin, out of these 3 are for office 2003 and 3 for office 2007. So my single msi should install only 3 addon based on the version of office. And there are some prerequisites that i want to install before these msi.
I tried using wix for once it created a setup but after sometime same project gave error: "Error 1 Unresolved reference to symbol 'ChainPackageGroup:wwwwww' in section 'Bundle:wixB2'" .
Setup creted by wix was able to install the setups but was not able to uninstall them, may be uninstallation needed admin rights but i was not able to give.
I also tried dotnetinstaller but i could not find how to add launch condition for my 6 installers. (Inatllcheck in dotnetinstaller only checks existense of the product getting install not the launch condition) If anybody can tell me how to add launch condition like if office 2007 present then install else do not, I will be able to complete my project if somebody help me to add launch condition.
So can you please tell me what should I do to create a single installer?

I Am also new to Wix. If You post your code It will be Helpful to solve your problem. You can go through following approach it might help you.
Considering user have office 2007 installed on his system your installer should install only Add-Ins for 2007. and as you have executables for add-ins Bootstrapper is best approach for it.
For Conditional installation you first need to find which version of office is already installed.
This you can do using Registry Search
<util:RegistrySearch Id ="Office2007" Root="HKLM" Key="SOFTWARE\Microsoft\Office\12.0\Word\InstallRoot::Path"/>
This will search in specific path.
Now for Installation
<ExePackage Id="2007Addin" SourceFile="your addin path"
InstallCondition="(Office2007)"/>
There are many other useful arguments also. go through them.
Sample Program
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"
xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
<Bundle Name="WordAddin" Version="1.0.0.0" Manufacturer="NSS" UpgradeCode="51d04319-a135-487c-a4bb-aed77417bda7">
<BootstrapperApplicationRefId="WixStandardBootstrapperApplication.RtfLicense" />
<util:RegistrySearchRef Id ='Office2007'/>
<--Here Install condition parameter checks if specific key is found if found installs packege -->
<--You can use NOT Office2007found this will install only if registry key not found-->
<Chain>
<MsiPackage Id ="officeAddin" Compressed='yes' Cache='yes' Name='office addin' SourceFile='officeadd.msi' InstallCondition='Office2007found' DisplayInternalUI='yes'/>
</Chain>
</Bundle>
<!--Registry Search to find Which Office Version Is installed (incase registry search failed change keys according)-->
<Fragment>
<util:RegistrySearch Id="office2007" Root="HKLM" Key="SOFTWARE\Microsoft\Office\12.0" Value="Version" Variable="Office2007found"/>
<--Below condition is only to check whether registry search is successful or not. remove it if not required-->
<bal:Condition Message="Failed to search regKey">Office2007found</bal:Condition>
</Fragment>
</Wix>
For Your Reference
wix installer 3.7 bootstrapper Registry search
How to detect installed version of MS-Office?
http://www.c-sharpcorner.com/UploadFile/cb88b2/installing-prerequisites-using-wix-bootstrapper-project-and/
Launch Condition to Detect Office 2010 Applications

Related

Implement dependency of ExePackage on other MSI so uninstall completes if required MSI was already removed

Background:
I have a large project which consists of a server component, client component and microservice hosting component. Each is packed in its own MSI.
The server component and the microservice hosting component each install a Windows service.
The server components' Windows service depends on the microservice hosting components' Windows service.
Everything is chained together and distributed by a setup bundle *.exe installer. In the installer, a customer can choose if he wants to install only the client, only the server or both (client and server).
At the end of the installation the customer is informed that everything went well (all files copied, all services running) (= success message) or not (= failure message with the possibility to send the log files to our help desk).
Updates are implemented as MajorUpgrades since the setup consists of hundreds of files. Our customers expect that if an update fails, the setup "rolls back" to the previously installed version of the product (= the whole bundle).
What lead to the problem?
Since Wix v3 does not handle rollbacks of bundles the way I expect it (see here) -- only the MSI that triggered the failure is rollbacked, previously installed MSIs in the chain before are only removed -- we had to implement a few workarounds:
install the component, which most likely causes errors on a customer machine, first -- then install the other MSIs.
deal with the Windows service dependencies of the components later (= restart the server component service)
Point 2 is achieved by using ExePackages that start and stop the servers' Windows service. This is done by using the technique described here. The service component MSI does not start the Windows service, only stops it on uninstall.
For architectural reasons, I do not want to configure the service components' Windows service in the microservice hosting service MSI.
This lead to the following Wix source code:
Bundle.wxs
<Chain>
            <PackageGroupRef Id="SqlExpress"/>
            <PackageGroupRef Id="vcredist"/>
            <!-- ... -->
            <PackageGroupRef Id="ServiceHandlingStop" />
            <PackageGroupRef Id="Server"/>
            <PackageGroupRef Id="MicroServiceHost"/>
            <PackageGroupRef Id="ServiceHandlingStart" />
            <PackageGroupRef Id="Client"/>
        </Chain>
Fragment of the "service handling":
The decision of the user what to install is stored inside "InternalInstallType"
<Fragment>
<PackageGroup Id="ServiceHandlingStop">
<ExePackage Id="ServiceHandlingStopCall"
Compressed="yes"
DisplayName="Service Management"
SourceFile="redist\Runner.bat"
InstallCommand="net stop WCFHostService"
UninstallCommand="net start WCFHostService"
DetectCondition="WixBundleInstalled = 1 AND InternalInstallType <> "Client""
InstallCondition="InternalInstallType <> "Client""
Permanent="no"
Vital="no"
PerMachine="yes">
<ExitCode Behavior="success" />
</ExePackage>
</PackageGroup>
<PackageGroup Id="ServiceHandlingStart">
<ExePackage Id="ServiceHandlingStartCall"
Compressed="yes"
DisplayName="Service Management"
SourceFile="redist\Runner.bat"
InstallCommand="net start WCFHostService"
UninstallCommand="net stop WCFHostService"
DetectCondition="WixBundleInstalled = 1 AND InternalInstallType <> "Client""
InstallCondition="InternalInstallType <> "Client""
Permanent="no"
Vital="yes"
PerMachine="yes">
<ExitCode Value="0" Behavior="success" />
<ExitCode Behavior="error" />
</ExePackage>
</PackageGroup>
</Fragment>
What should be achieved by this bunch of code?
"Only if the server component is installed, start the server components' Windows service after the microservice hosting component is installed. On a failed upgrade, start the server components' Windows service after the previous version was installed again. If the user chooses to uninstall, don't care about the server components' Windows service."
The problem
If the setup bundle on uninstallation by a user is killed / closed unexpectedly, it can occur that some of the MSIs mentioned in the chain above are already installed.
Now if the user launches the setup again to uninstall once more, Burn runs the ExePackage ServiceHandlingStartCall again and since is marked as Vital=yes (to inform the user if the service startup succeeded on install, upgrade and rollback and abort if neccessary), the setup fails and the user is unable to remove the product.
Question:
How to implement the dependency between the ExePackage ServiceHandlingStartCall and the service component MSI so uninstallation is possible even though the other MSIs are already gone?
I tried
"InstallCondition" / "DetectCondition"
Dependency I don't find any examples / documentation
Or if someone has an idea of how to handle the dependency of server component and microservice hosting component, my ears are wide open.
Thank you!
Are you able to check whether the individual compoments (MSIs) are installed?
It seems you're only checking if the entire bundle is installed or not (WixBundleInstalled = 1). Even though the InternalInstallType variable holds the "decision of the user what to install", that might not reflect the actual state of the system if the installer was previously interrupted, as you're describing.
If you could make every component (MSI) mark if it is installed or not (in the registry, for example) you could then do a RegistrySearch in Wix and only try to uninstall the component if it was detected.
I've implemented the same thing recently. This code check if the WebView2 Runtime is already installed, before attempting to install it:
Bundle.wxs (Bootstrapper)
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:bal="http://schemas.microsoft.com/wix/BalExtension"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Bundle ...>
... code removed for brevity
<!-- Check if WebView2 Runtime already installed -->
<util:RegistrySearch
Root="HKLM"
Key="SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}"
Value="pv"
Variable="WV2RuntimeMachineVersion" />
<util:RegistrySearch
Root="HKCU"
Key="SOFTWARE\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}"
Value="pv"
Variable="WV2RuntimeUserVersion" />
<Chain>
<!--This will only be installed when INSTALLING or REPAIRING and the WebView2 Runtime is not already installed-->
<ExePackage Id="TheWebView2Runtime"
DisplayName="WebView2 Runtime"
Vital="no"
Cache="no"
Permanent="yes"
SourceFile="..\..\data\bundle\MicrosoftEdgeWebView2RuntimeInstallerX64.exe"
InstallCommand="/silent /install"
DetectCondition="NOT (WixBundleAction = 5 OR WixBundleAction = 7) OR (WV2RuntimeMachineVersion >= v102.0.1245.22 OR WV2RuntimeUserVersion >= v102.0.1245.22)" />
</Chain>
</Bundle>
</Wix>
Note that in my case, I don't want to uninstall the dependency (WebView2 Runtime) ever, but that could easily be changed by removing the NOT (WixBundleAction = 5 OR WixBundleAction = 7) of the DetectCondition.
Do you think this approach might work for you?

Wix ExePackage Side by Side Install without Uninstall

I have two products which I'm trying to write an installer for. Both products are wix bundles which both have a third product bundle as a requirement.
Ideally what I want to happen when you install one is:
If Product3 is not installed then it should be.
If Product3 is installed and installed version is higher or the same do nothing.
If Product3 is installed and installed version is lower then upgrade.
If uninstalling and product1 or 2 is still installed do not uninstall product3.
So far I was able to conquer some of these points but not all at the same time.
Originally I tried getting the installed version using a ProductSearch and using InstallCommand. However I ran into problems with uninstalling when doing side by side installs because the installcommand is more like "requested install state" and so if I don't want it to install when it detects the same version it actually starts uninstalling it.
I took a look at this similar answer:
How to avoid uninstalling previously installed ExePackage (redistributables) while installing a WiX Bundle?
which suggested using the provideskey and requires elements but I cannot find any useful documentation on them whatsoever. I tried experimenting with it but it doesn't seem to do anything at all.
I've looked at RelatedBundle but I'm not sure it's what I'm after. Seems more targeted at hotfixing systems.
I was hoping there was a way of doing this without having to resort to custom actions since that seems a bit extreme for what seems to be rather simple functionality.
After a lot of trial and error I figured out how to get the DependencyExtension working.
In the example below ProductC is a Wix Bundle executable. This bundle includes an MSI file. I use a productSearch to look for the upgrade code of that MSI file (NOT THE BUNDLE) to detect if it's already installed.
In your bundle file for project A and B:
<Wix xmlns:dep="http://schemas.microsoft.com/wix/DependencyExtension"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Bundle>
<util:ProductSearch Id="ProductCInstallSearch"
UpgradeCode="{ProductC_MSI_UpgradeCode_GUID}"
Variable="ProductCInstalled"
Result="state"/>
<dep:Requires Id="ProductCRequired" ProviderKey="ProductC"/>
<Chain>
<PackageGroupRef Id="ProductC_pkg"/>
</Chain>
</Bundle>
<Fragment Id="Required_Pkgs">
<PackageGroup Id="ProductC_Pkg">
<ExePackage Id="ProductC_Bundle"
Permanent="no"
DetectCondition="NOT ProductCInstalled = 2"
InstallCommand="/quiet"
UninstallCommand="/uninstall /quiet">
<dep:Provides Key="ProductC"
Version="0.0.0.0">
<dep:RequiresRef Id="ProductCRequired"/>
</dep:Provides>
</ExePackage>
</PackageGroup>
</Fragment>
</Wix>
Now you can install A and B in any arrangement and when uninstalling product C will only be removed when the last one is uninstalled.

WIX Conditional Message on Exit

I have a WIX installer which I need to also install the VC++ 2015 runtime executable. I'm using the vcredist_x64.exe as opposed to the merge modules (see this thread). I can successfully launch the vcredist_x64.exe after my msi finishes installing my application by using a custom action... however, what I'd like to do is first check to see if the runtime files already exist. If they do, then I'll just finish without running the vcredist_x64.exe. Otherwise, I'll run the custom action to install the runtimes as well.
It took some digging, but I was able to find out that the 2015 runtimes have a registry key shown below:
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\14.0\VC\Runtimes\x64
with an Installed value of 1 if they exist.
So, in my .wxs file I have the following registry search:
<!-- Visual C++ 2015 x64 -->
<Property Id="VCREDISTRUNTIMES2015INSTALLED">
<RegistrySearch Id="VCREDISTRUNTIMES2015SEARCH" Root="HKLM" Key="SOFTWARE\WOW6432Node\Microsoft\VisualStudio\14.0\VC\Runtimes\x64" Name="Installed" Type="raw" />
</Property>
Now, what I'd like to do is show a message on my exit dialog which says that if the runtimes aren't detected, then it will launch an installer to install them upon exit. Something like this:
<Property Id="WIXUI_EXITDIALOGOPTIONALTEXT" Value="Visual C++ Redistributable for Visual Studio 2015 is Required. Installation will proceed on exit.">
<Condition>VCREDISTRUNTIMES2015INSTALLED</Condition>
</Property>
However, this doesn't work. I get an error on the conditional tag and the project wont build. Assuming my registry search is setup correctly, can someone tell me how to properly add a conditional message on my exit dialog? Thanks!
Answering my own question... but here goes. It turns out that my registry search was just fine... but I needed to use "SetProperty" instead. So, something like this:
<SetProperty Id="WIXUI_EXITDIALOGOPTIONALTEXT" After="AppSearch" Value="The Visual C++ Redistributable Package for Visual Studio 2015 is Required. Installation will now install run-time components that are required to run C++ applications built using Visual Studio 2015.">
NOT VCREDISTRUNTIMES2015INSTALLED
</SetProperty>
Now, if the VCREDISTRUNTIMES2015INSTALLED is null (or false) then it will show the message on the exit dialog. Otherwise, there will be no message shown. Hope that helps.

Upgrade older msi from Wix custom BA Bundle

We are upgrading our WIX msi installer (not a bundle) with manual pre-requisites to a Managed custom Bootstrapped application Bundle. The boot strapped custom installer bundle exe works fine for fresh installs. But if we want to upgrade our older product which is just an msi, we are in trouble. This is what I am trying to do
Detect RelatedMsiFeatureHandler detects there is an older msi package installed.
I am handling the Plan events for individual packages and setting the states as desired. For ex: state = Present for install
I cannot to Apply(UpdateReplace) because I do not have an older Bundle,
The million dollar question is how do I upgrade this msi package?
Any help is appreciated.
Thanks
All I had to do was set the MsiProperty UPGRADE=1 in Bundle.wxs for the relevant Msi Package in the chain. This made sure that when the Bundle.exe is run the specific msi is upgraded BTW: this is the first version of Bundle for us. We had just an MSI before for installation.
<MsiPackage DisplayName="Installing Main Product" SourceFile="$(var.Path_Setup)" DisplayInternalUI="no" SuppressSignatureVerification="yes" >
***<MsiProperty Name="UPGRADE" Value="1"/>***
<MsiProperty Name="NAS_PATH" Value="[NasBackupPath]"/>
<MsiProperty Name="NAS_BAK_TIME" Value="[BackupTime]"/>
</MsiPackage>
</Chain>
Just in case if anyone having similar issue (WIX 3.10)
this statment under the installer's Product will resolve the issue. You must update the version of the product and product upgrade code must be same with previous install.
"AllowSameVersionUpgrades" = yes will make sure not to install same product side by side.

How to deploy 64-bit and a 32-bit Windows Installer package as a single setup?

I need to deploy a software setup targeting both, Windows 64bit and 32bit. I have two separate Windows Installer databases (created with WiX) for each platform, and I am using dotNetInstaller to combine both into a single installation bootstrapper executable.
I'm currently using version 1.10 of dotNetInstaller and set auto_close_if_installed=True, because I want to comletely hide the bootstrapper from the user. Still, dotNetInstaller insists on displaying a sill progress bar window while my installer is running, and doesn't really auto-close. The user needs to confirm a dialog box telling him that the application was successfully installed. But the real deal-breaker is that it doesn't support Windows 8 (yet).
Upgrading to a later version of dotNetInstaller seems to break auto_close_if_installed, so it's even worse.
So my question is: what is the current state of the art to deploy both setups in a single executable. Would Wix Burn be an option?
I know that in an ideal world, I simply provide my customers with separate installers for either platform. But they happen to be completely unaware of such subtleties, most of them don't even know what platform they are using.
I would definitely use Burn in this scenario. Something akin to the following:
<Wix>
<Bundle...>
<BootstrapperApplicationRef Id='WixStandardBootstrapperApplication.HyperlinkLicense' />
<Chain>
<MsiPackage InstallCondition='NOT VersionNT64' SourceFile='path\to\x86.msi' />
<MsiPackage InstallCondition='VersionNT64' SourceFile='path\to\x64.msi' />
</Chain>
</Bundle>
</Wix>
This is exactly one of the scenarios Burn was designed to handle.
You can do it in a single Wix via Conditions and Features.
<Feature Id='X86' Level='1'>
<ComponentRef Id='X86Feature1' />
<Condition Level="1">NOT VersionNT64</Condition>
</Feature>