Start application after installation using WiX/Burn
Asked Answered
T

3

19

I'm aware of similar questions in WiX MSI, but I'm having issues starting an application within a bootstrapper EXE file created with Burn after the installation. My full bundle is below.

If it makes any difference to the scenario, the bootstrapper is started in passive mode, so the user shouldn't need to press anything.

<?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 Name="My Company AutoUpdater"
            Version="1.0.11"
            Manufacturer="My Company"
            UpgradeCode="--GUID--">

        <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.HyperlinkLicense">

            <bal:WixStandardBootstrapperApplication SuppressOptionsUI="yes"
                                                    LicenseUrl=""
                                                    LogoFile="logo.png" />
        </BootstrapperApplicationRef>

        <Chain>
            <MsiPackage SourceFile="..\App1\bin\Release\App1.msi" />
            <MsiPackage SourceFile="..\App2\bin\Release\App2.msi" />
        </Chain>
    </Bundle>

    <Fragment>
        <Property Id="WixShellExecTarget" 
                  Value="[#C:\Program Files (x86)\My Company\App1.exe]" />

        <Binary Id="MyCA"
                SourceFile="[#C:\Program Files (x86)\My Company\App1.exe]"/>

            <CustomAction Id="LaunchApplication"
                          BinaryKey="MyCA"
                          ExeCommand="-switch"
                          Execute="deferred"
                          Return="check"
                          HideTarget="no"
                          Impersonate="no" />

            <InstallExecuteSequence>
                <Custom Action="LaunchApplication" 
                        After="InstallFiles" />
            </InstallExecuteSequence>
    </Fragment>
</Wix>
Twocolor answered 10/10, 2012 at 16:5 Comment(0)
T
5

It had a number of steps. Remember I was running this from a bootstrapper, not an MSI file, whereby levarius's answer would have sufficed.

Basically, I removed any of the launch logic that was posted in the original question, and created a new package, whose sole functionality was to kick off an application (using a custom action), and whose location had previously been saved in the registry - that is, the application running when it found that an update was available, set this item in the registry.

The package (called PostInstall below) is then run ONLY if one of the other packages has been installed previously - found by the existence of a key in the registry (set in each product's MSI). This means that no application will be started automatically after a new install has completed.

The following is from the bootstrapper bundle (WiX 3.6 in my case)

<!-- Determine what items are installed in the event of an upgrade-->
<util:RegistrySearch Root="HKLM"
                     Key="SOFTWARE\CompanyName"
                     Value="ProductAInstalled"
                     Variable="ProductAInstalled"
                     Result="exists"
                     Format="raw" />
<util:RegistrySearch Root="HKLM"
                     Key="SOFTWARE\CompanyName"
                     Value="ProductBInstalled"
                     Variable="ProductBInstalled"
                     Result="exists"
                     Format="raw" />

<Chain>
    <!-- Package for .NET prerequisite. References a Package that is
         actually in the referenced WiX file WixNetFxExtension. -->
    <PackageGroupRef Id="NetFx40Web"/>

    <MsiPackage SourceFile="..\SetupProductA\bin\Release\SetupProductA.msi"
                InstallCondition="(chkProductA) OR (ProductAInstalled)" />

    <MsiPackage SourceFile="..\SetupProductB\bin\Release\SetupProductB.msi"
                InstallCondition="(chkProductB) OR (ProductBInstalled)" />

    <!-- Run PostInstall only if this was run as part of an upgrade. -->
    <!-- NB: This is the portion that kicks off the downloaded bootstrapper. -->
    <MsiPackage SourceFile="..\PostInstall\bin\Release\PostInstall.msi"
                InstallCondition="(ProductAInstalled) OR (ProductBInstalled)" />
</Chain>
Twocolor answered 28/3, 2013 at 13:7 Comment(5)
I'm having the same problem and I think this solution is great. However, I'm just curious as to how PostInstall.msi launches the executable? Could you post how it reads the path from the registry and then executes the file? I'm a WiX noob and don't know how. Also, is there a way to show a checkbox that the user can check or uncheck to determine if they'll launch PostInstall.msi? (this checkbox would have to be in the bootstrapper's UI, not the msi's)Ovule
Anyone know if this is still the best way to do this?Agan
Ian - I'd be interested as well. We're still using this method, as to be honest it's been pretty faultless and have thus far not needed to upgrade WiX to the later versions (we're still using 3.6). There have been quite a few related burn changes since then, so you're asking a wise question... (& sorry I do not know the answer!)Twocolor
'LaunchTarget' variable is designated for this. Chaining is dedicated to install the MSI or Exe based on the conditions. What if the user doesn't want to start/launch your application right away? isn't it a good design to let the user decide what they want to do with your installer?Idio
In this instance they will have already been given the option to update the app on startup, so the rest is done seamlessly in the background, and the same (now update) app restarts after the update. Sorry missed your original comment...Twocolor
C
20

You can add a variable to your Bundle called "LaunchTarget" with a path to the executable you want to run:

<Variable Name="LaunchTarget" Value="[InstallFolder]\path\to\file.exe"/>

After the install, the Setup Successful screen will display a "Launch" button that will start your app.

Concussion answered 11/10, 2012 at 18:2 Comment(3)
Hi levarius thanks for the reply. I can create the launch button which works fine no problem when the user clicks on the MSI. Unfortunately this method doesn't work when the MSI is launched in passive mode (ie where the user has no interaction in the process - like this.. Process.Start("Bootstrapper.exe", "/passive"); ). In this scenario the MSI simply terminates without "using" the launch target.Twocolor
Yes, I don't believe that you can automatically "Launch" the executable using the standard bootstrapper application from passive mode. You may have to write your own BA and implement Launch from passive mode on your own.Concussion
[InstallFolder] is blank for me, i'm using <Chain>Naima
T
5

It had a number of steps. Remember I was running this from a bootstrapper, not an MSI file, whereby levarius's answer would have sufficed.

Basically, I removed any of the launch logic that was posted in the original question, and created a new package, whose sole functionality was to kick off an application (using a custom action), and whose location had previously been saved in the registry - that is, the application running when it found that an update was available, set this item in the registry.

The package (called PostInstall below) is then run ONLY if one of the other packages has been installed previously - found by the existence of a key in the registry (set in each product's MSI). This means that no application will be started automatically after a new install has completed.

The following is from the bootstrapper bundle (WiX 3.6 in my case)

<!-- Determine what items are installed in the event of an upgrade-->
<util:RegistrySearch Root="HKLM"
                     Key="SOFTWARE\CompanyName"
                     Value="ProductAInstalled"
                     Variable="ProductAInstalled"
                     Result="exists"
                     Format="raw" />
<util:RegistrySearch Root="HKLM"
                     Key="SOFTWARE\CompanyName"
                     Value="ProductBInstalled"
                     Variable="ProductBInstalled"
                     Result="exists"
                     Format="raw" />

<Chain>
    <!-- Package for .NET prerequisite. References a Package that is
         actually in the referenced WiX file WixNetFxExtension. -->
    <PackageGroupRef Id="NetFx40Web"/>

    <MsiPackage SourceFile="..\SetupProductA\bin\Release\SetupProductA.msi"
                InstallCondition="(chkProductA) OR (ProductAInstalled)" />

    <MsiPackage SourceFile="..\SetupProductB\bin\Release\SetupProductB.msi"
                InstallCondition="(chkProductB) OR (ProductBInstalled)" />

    <!-- Run PostInstall only if this was run as part of an upgrade. -->
    <!-- NB: This is the portion that kicks off the downloaded bootstrapper. -->
    <MsiPackage SourceFile="..\PostInstall\bin\Release\PostInstall.msi"
                InstallCondition="(ProductAInstalled) OR (ProductBInstalled)" />
</Chain>
Twocolor answered 28/3, 2013 at 13:7 Comment(5)
I'm having the same problem and I think this solution is great. However, I'm just curious as to how PostInstall.msi launches the executable? Could you post how it reads the path from the registry and then executes the file? I'm a WiX noob and don't know how. Also, is there a way to show a checkbox that the user can check or uncheck to determine if they'll launch PostInstall.msi? (this checkbox would have to be in the bootstrapper's UI, not the msi's)Ovule
Anyone know if this is still the best way to do this?Agan
Ian - I'd be interested as well. We're still using this method, as to be honest it's been pretty faultless and have thus far not needed to upgrade WiX to the later versions (we're still using 3.6). There have been quite a few related burn changes since then, so you're asking a wise question... (& sorry I do not know the answer!)Twocolor
'LaunchTarget' variable is designated for this. Chaining is dedicated to install the MSI or Exe based on the conditions. What if the user doesn't want to start/launch your application right away? isn't it a good design to let the user decide what they want to do with your installer?Idio
In this instance they will have already been given the option to update the app on startup, so the rest is done seamlessly in the background, and the same (now update) app restarts after the update. Sorry missed your original comment...Twocolor
D
4

Use the advice given in the WiX manual, How To: Run the Installed Application After Setup. There is a built-in WiX extension that will handle this for you. You should be able to reference the WiX Util extension, add the following code to your project (replacing the value of the property of course), then schedule the action to run:

<Property Id="WixShellExecTarget" 
          Value="[#myapplication.exe]" />
<CustomAction Id="LaunchApplication" 
              BinaryKey="WixCA" 
              DllEntry="WixShellExec" 
              Impersonate="yes" />
Danu answered 10/10, 2012 at 22:40 Comment(4)
Hi heavyd, I have indeed though I'm actually trying to do it in a bootstrapper app via burn, rather than an wix msi. However, going back to basics to ensure I could do it with an msi as explained in your link, I'm unable even to do that - I've copied & pasted the finished example, created a basic install which installs fine but again nothing once the install is finished - pastbin here [link]pastebin.com/sCiikjAJ (which is 99% the same as the example above..)Twocolor
I believe that there is an additional <Publish /> directive that needs to be added to the UI section for this to work. I just tried it and it works fine for me.Katzenjammer
This worked perfectly for me, thanks! I copied the above code, then scheduled the Custom Action in the InstallExecuteSequence, like <Custom Action="LaunchApplication" After="InstallFinalize"/>Offenbach
Thank you @grefly! You code was the missing piece of the puzzle. ;)Alp

© 2022 - 2024 — McMap. All rights reserved.