Placing an executable and an MSI in a bundle, in a bootstrapper

Oct 29, 2015 at 8:59 PM
I would like to place an Adobe Installer in my bootstrapper. Are there examples how to do that?

I want the bootstrapper to bundle an MSI file and the Adobe Installer and of course install the bundle.

Thanks!
Coordinator
Oct 30, 2015 at 11:04 AM
You will need to use ExePackage class similarly to the MsiPackage class in the Bootstrapper samples.
Though if your Adobe setup is a "exe+msi" package then you will need to embed the msi file into ExePackage.Payload.
Oct 30, 2015 at 5:52 PM
Thank you, that seemed to work!

My next issue is uninstalling what I just installed. When I bring up the control panel's Uninstall window, I can see the name of my bootstrapper and the Adobe installation in the list.

When I click on uninstall, the application installed with the MSI part of the bundle gets un-installed, and my bootstrapper un-installs itself. But the Adobe app remains installed.

How do I link the uninstall of the the bootstrapper with Adobe's uninstall? I want the entire stack of applications linked/bundled together so everything installs and uninstalls in one request.

BTW: I don't know if the adobe setup exe is an "exe+msi" or just an "exe". How does one determine if an exe file is both?

Sorry about all these new-bee beginner questions. I have never written an installer before and WixSharp seemed easier to learn since I am comfortable with C#.

Thanks!
Coordinator
Nov 4, 2015 at 4:02 AM
> I don't know if the adobe setup exe is an "exe+msi" or just an "exe". How does one determine if an exe file is both?
It's actually easy. If the product can be installed by executing a stand alone *.exe (e.g. setup.exe) then the .msi is embedded into the bootstraper application (.exe file). However if the setup .exe requires an .msi to be present in the same location then it is an "exe+msi" setup and the product can be installed only if both msi and exe are present.

The actual choice of the model (single exe vs exe+msi) will always depend on the implementation of the deployment framework that was used to author the bootstrapper application. For example WiX Burn always embeds msi files into exe (at least by default).

> ...my bootstrapper un-installs itself. But the Adobe app remains installed.
It is actually not an unusual problem. Particularly when you are using third-party bootstrappers (setup.exe) inside of your bootstrapper. One of the possible reasons is that during uninstall your bootstrapper doesn't pass the 'magic' uninstall argument into your dependency setup.exe. This can be '/u' or '/uninstall' or what ever Adobe guys decided to use. You normally control this with ExePackage.UninstallCommand.
Another possible reason is that during the uninstall session your bootstrapper doesn't detect correctly that Adobe reader is already installed. You normally use ExePackage.DetectCondition. This is what the doculmentation says about it:
A condition that determines if the package is present on the target system. This condition can use built-in variables and variables returned by searches. This condition is necessary because Windows doesn't provide a method to detect the presence of an ExePackage. Burn uses this condition to determine how to treat this package during a bundle action; for example, if this condition is false or omitted and the bundle is being installed, Burn will install this package.
It is a generic WiX/Burn challenge and most likely you will find something on the subject if you google for "burn uninstall adobe".
Nov 25, 2015 at 4:26 PM
Thank you!

Now I need an example of how to use the DetectCondition. Suppose the Adobe Reader is already installed and I am using the Adobe installer as one of my packages in my bootstrapper.

var adobePackage = new ExePackage("AdobeReader.exe");
adobePackage.InstallCondition = "C:Program Files (x86)\Adobe\Reader 11.0\Reader\AcroRd32";

If that full path and filename exists, then the bootstrapper will NOT install? Is that a true statement?

Thanks!
Nov 25, 2015 at 4:32 PM
adobePackage.InstallCondition = "C:Program Files (x86)\Adobe\Reader 11.0\Reader\AcroRd32exe";

I forgot the ".exe" in the comment.
Nov 25, 2015 at 4:53 PM
Execuse me... I meant to say the bootstrapper will NOT run the Adobe installer.

Sorry about that. I do my best editing after I enter the message!
Nov 25, 2015 at 5:49 PM
Ok.. .one more. Sheesh I am really making crazy errors in these boards!

Change adobePackage.InstallCondition to adobePackage.DetectCondition
Coordinator
Nov 26, 2015 at 3:34 AM
The DetectCondition value is not a location of the file but a string expression containing WiX/Burn variables. For example the result of a file search:
<Chain>
    <util:FileSearchRef Id="AdobeSearch"/>
    <ExePackage SourceFile="adobe_setup.exe" DetectCondition="AdobeReaderInstalled" .../>
...
<Fragment>
    <util:FileSearch
        Id='AdobeSearch'
        Variable="AdobeReaderInstalled"
        Result="exists"
        Path="[ProgramFilesFolder]Adobe\Reader 11.0\Reader\AcroRd32exe" .../>
Nov 30, 2015 at 11:47 AM
Thank you.

I am a bit confused though. Do I also have to write up an XML with the Wix Tool Set to compose this code in the example you gave? I was hoping for an example with C#/WixSharp

Is there an example of what I need in the sample code?

Thanks again.
Coordinator
Dec 1, 2015 at 4:53 AM
Indeed typically Wix# produces the all required XML behind the scene so you don't need to deal with raw XML.

However if some WiX features are not supported directly then you may need to define the corresponding XML explicitly (see InjectXML sample). The same applies to the fragments. The fragments are pure XML decoration feature of WiX and as such it's hard to map it to the object model of the Wix# project definition.

This is how you can inject the required XML it in your case:
bootstrapper.WixExtensions.Add("WixUtilExtension");
bootstrapper.WixNamespaces.Add("xmlns:util=\"http://schemas.microsoft.com/wix/UtilExtension\"");
bootstrapper.WixSourceGenerated += Bootstrapper_WixSourceGenerated;
...
static void Bootstrapper_WixSourceGenerated(System.Xml.Linq.XDocument document)
{
    var ns = document.Root.GetNamespaceOfPrefix("util");

    document.Root.Add(new XElement("Fragment",
                            new XElement(ns + "FileSearch")
                                .AddAttributes(@"Id=AdobeSearch;
                                                Variable=AdobeInstalled;
                                                Result=exists;
                                                Path=[ProgramFilesFolder]Adobe\\...\\adobe.exe")));

    document.Select("Wix/Bundle/Chain")
            .AddBeforeSelf(new XElement(ns+"FileSearchRef")
                                .SetAttribute("Id=AdobeSearch"));
}
However the next Wix# release will have a method extension that will simplify the task a little
document.Select("Wix/Bundle")
        .AddWixFragment(new XElement(WixExtension.Util.ToXName("FileSearch"),
                                   @"Variable=AdobeInstalled;
                                     Result=exists;
                                     Path=[ProgramFilesFolder]Adobe\\...\\adobe.exe".ToXAttributes()));
Dec 1, 2015 at 7:04 PM
Thank you, again!

Just one more.... is there a way to do that with the registry instead of looking for the "adobe.exe" binary that gets installed?

The registry for Adobe is in the "current user" section under @"Software\Adobe\Acrobat Reader\11.0"
Coordinator
Dec 1, 2015 at 10:15 PM
Yes there is a way. You will need to use RegistrySearch fragment instead of FileSearch. BTW the yesterday release has delivered AddWixFragment API.

However if you are asking about the registry key that indicates that AdobeReader is installed then you will need to do your own research on this as the way the product is deployed is entirely up to the software vendor.