Executing Custom Action after adding system variable in Wix - wix

I am adding system variables and then i want to execute custom actions, that depends on those variables. The variables are being added correctly, but the scripts are exiting ( because at that time variables are not there yet ), depsite the fact I am using "After Install Files". Here is my code:
<?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="*" Name="DataBaseds_Service_Installer" Language="1033" Version="1.0.0.0" Manufacturer="" UpgradeCode="3875ce89-3886-4cbf-b132-01f947ac7a08">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes" />
<CustomAction Id="NssmUnzip" Directory="INSTALLFOLDER" Execute="deferred" Impersonate="no" ExeCommand="cmd.exe /c "unzip.exe nssm-2.24.zip -d "%TANGO_ROOT%\bin" "" Return="ignore" />
<CustomAction Id="Tango_db" Directory="INSTALLFOLDER" Execute="deferred" Impersonate="no" ExeCommand="[INSTALLFOLDER]create-tangodb.bat" Return="ignore" />
<CustomAction Id ="Baseds_Service" Directory="INSTALLFOLDER" Execute="deferred" Impersonate="no" ExeCommand="[INSTALLFOLDER]Tango-DataBaseds.bat" Return="ignore" />
<CustomAction Id="UninstallService" Directory="INSTALLFOLDER" Execute="deferred" Impersonate="no" ExeCommand="[INSTALLFOLDER]Remove_Baseds_Service.bat" Return="ignore" />
<InstallExecuteSequence>
<Custom Action="NssmUnzip" After="InstallFiles">NOT Installed</Custom>
<Custom Action="Tango_db" After="NssmUnzip">NOT Installed</Custom>
<Custom Action="Baseds_Service" After="Tango_db">NOT Installed</Custom>
<Custom Action="UninstallService" After="InstallInitialize"> Installed and Not REINSTALL</Custom>
</InstallExecuteSequence>
<Property Id="DIRR">
<RegistrySearch Id="aaa" Root="HKCU"
Key="Software\corp\Tango"
Name="Directory"
Type="directory"/>
</Property>
<Feature Id="ProductFeature" Title="DataBaseds_Service_Installer" Level="1">
<ComponentRef Id="MYSQL_Path"/>
<ComponentRef Id="MYSQL_USER"/>
<ComponentRef Id="MYSQL_PASSWORD"/>
<ComponentGroupRef Id="Components" />
</Feature>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="DataBaseds_Service_Installer" />
</Directory>
</Directory>
<ComponentGroup Id="Components" Directory="INSTALLFOLDER">
<Component Id="NSSM" Guid="54CEB76C-6974-4071-96E9-EF5AD1937BD4">
<File Source="nssm-2.24.zip" KeyPath="yes" />
<File Source="Tango-DataBaseds.bat" KeyPath="no"/>
<File Source="Remove_Baseds_Service.bat" KeyPath="no"/>
<File Source="create-tangodb.bat" KeyPath="no"/>
</Component>
<Component Id="unzip" Guid="E10EE17A-AA5A-416B-82DF-37532281116C">
<File Source="unzip.exe" KeyPath="yes"/>
</Component>
</ComponentGroup>
<DirectoryRef Id="TARGETDIR">
<Component Id="MYSQL_USER" Guid="D05C8155-8421-4AEB-9A19-5016DAFAED19">
<Environment Id="MYSQL_USER" Name="MYSQL_USER" Value="root" Permanent="no" Part="last" Action="set" System="yes" />
</Component>
<Component Id="MYSQL_PASSWORD" Guid="222C7887-1E4D-4DC2-B429-A3F18F707FA3">
<Environment Id="MYSQL_PASSWORD" Name="MYSQL_PASSWORD" Value="tango" Permanent="no" Part="last" Action="set" System="yes" />
</Component>
<Component Id="MYSQL_Path" Guid="34D14695-1803-4D7E-AD65-3C9011D019CE">
<Environment Id="PATH" Name="PATH" Value="[DIRR]bin" Permanent="no" Part="last" Action="set" System="yes" />
</Component>
</DirectoryRef>
</Product>
</Wix>
Am I doing something wrong?
Greetings

There are two general issues with environment variables in Windows Installer:
When they are set they don't just automatically show up for running programs because Windows Installer doesn't send the "environment variables have changed" broadcast message until the end of the install. If you run a program AFTER that it will pick up the new values.
There is no reason for any running processes to pick them up unless they have a message loop and are prepared to deal with the (I think) WM_WININICHANGE message and reload the environment.
So none of your custom actions are going to pick up the new variables because they haven't been broadcast to the system yet and "committed". And yes, it's better to find another way to pass the data to the programs.

Phil is not wrong.
But here is my solution, if anyone will ever have the same problem:
Even though as Phil says: "system variables are not set during an installation:
Windows Installer doesn't send the environment variables have changed broadcast message until the end of the install, they are stored inside variable ( "DIRR" in this example) when you are reading the registry:
<Property Id="DIRR">
<RegistrySearch Id="aaa" Root="HKCU"
Key="Software\corp\Tango"
Name="Directory"
Type="directory"/>
</Property>
So you can run a script and pass them as argument:
<CustomAction Id="Tango_db" Directory="INSTALLFOLDER" Execute="deferred" Impersonate="no" ExeCommand="[INSTALLFOLDER]create-tangodb.bat ****"[DIRR]bin"****" Return="ignore" />
These way your batch file has access to the system variables, despite the fact that ther are not yet set in the system.
Hope that this helps :)

Related

Execute custom actions only on install or uninstall

I'm making installer with WiX 3.10. My original task is to copy Postgres files to target system, initialize cluster, register service, start it and restore database on install, and in reverse - stop service, remove it from system, and clear up cluster data. I wrote two bat files, and added custom actions to execute them and some conditions as described in various places, but none of them working. I've tried with and without CDATA, Installed, INSTALLED and some other variations, but it always executes both actions.
Here is the wix file I'm experimenting with now.
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="Hatred_6" Language="1033" Version="1.0.0.0" Manufacturer="Satan" UpgradeCode="d9602b10-8428-4031-8c82-99288b21377f">
<Package InstallerVersion="405" Compressed="yes" InstallScope="perMachine" InstallPrivileges="elevated"/>
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes" />
<CustomAction Id="AAction" Directory="INSTALLFOLDER" Execute="deferred" Impersonate="no" Return="check"
ExeCommand="cmd.exe /c "a.bat"">NOT Installed</CustomAction>
<CustomAction Id="BAction" Directory="INSTALLFOLDER" Execute="deferred" Impersonate="no" Return="check"
ExeCommand="cmd.exe /c "b.bat"">Installed</CustomAction>
<InstallExecuteSequence>
<Custom Action="BAction" After="InstallFiles" />
<Custom Action="AAction" After="InstallFiles" />
</InstallExecuteSequence>
<Feature Id="ProductFeature" Title="Hatred_6" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="Hatred_6" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="CalcComponent" Guid="515C0606-FD73-4B5D-ACF4-481123092A3E">
<File Id="CalcFile" KeyPath="yes" Source="calc.exe" />
</Component>
<Component Id="AComponent" Guid="515e3aa0-e5a0-4cd1-aaa5-ebf25a679a24">
<File Id="AFile" KeyPath="yes" Source="a.bat" />
</Component>
<Component Id="BComponent" Guid="85f7627e-fc39-4f78-a870-221d2d08375d">
<File Id="BFile" KeyPath="yes" Source="b.bat" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>
bat files contain dir > a.txt and dir > b.txt so I can see if they actually executed.
It's somewhat frustrating, am I misunderstanding something?
Condition should be placed inside Custom element, not CustomAction. Also, you have no InstallFiles action during uninstalling. Use RemoveFiles instead.
<CustomAction Id="AAction" Directory="INSTALLFOLDER" Execute="deferred"
Impersonate="no" Return="check" ExeCommand="cmd.exe /c "a.bat"" />
<CustomAction Id="BAction" Directory="INSTALLFOLDER" Execute="deferred"
Impersonate="no" Return="check" ExeCommand="cmd.exe /c "b.bat"" />
<InstallExecuteSequence>
<Custom Action="AAction" After="InstallFiles">NOT Installed</Custom>
<Custom Action="BAction" Before="RemoveFiles">Installed</Custom>
</InstallExecuteSequence>

My Wix project is only showing up for me in Add/Remove but not other people?

We've been using Wix to create our website msi for awhile and it install fine.
Issue (Little annoyance) -
If I install my msi, it will show up in add/remove programs but if Person B goes on the server, my msi entry will not show up for them in Add/Remove programs.
I'm assuming it's a property to set in the wix product.wxs page but google hasn't been friendly to me in that regard.
I wasn't sure if it was a win2k3 issue only but we just did a test on a win2k8R2 and the same issue occured.
Here's my product.wxs file
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:iis="http://schemas.microsoft.com/wix/IIsExtension">
<Product Id="*"
Name="!(loc.ProductName)"
Language="!(loc.LANG)"
Version="1.0.0.0"
Manufacturer="!(loc.CompanyName)"
UpgradeCode="1bf00ad4-a8a1-407b-8a07-0d3046cb7214">
<Package InstallerVersion="200" Compressed="yes" Manufacturer="!(loc.CompanyName)" Description="!(loc.Description)" />
<?include Settings.wxi ?>
<?include Conditions.wxi ?>
<?include WebSites.wxi ?>
<iis:WebAppPool Id="AppPool" Name="[APP_POOL_NAME]"/>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="IISMain" Name='WebSites'>
<Directory Id="WWWMain" Name='SigappsTest'
ComponentGuidGenerationSeed='5A8C3E4A-0AA2-488C-80EC-91921A1A36CC'>
<Directory Id='INSTALLLOCATION' Name='!(loc.VirtualDirectory)'>
<!-- The component to define the Virtual Directory.-->
<Component Id="WebVirtualDirComponent" Guid="8AD62CCC-3FD5-4121-8370-DFB466482E61">
<iis:WebVirtualDir Id="VDir" Alias="[VD]" Directory="INSTALLLOCATION" WebSite="SelectedWebSite">
<iis:WebApplication Id="MyWebAppApplication" WebAppPool="AppPool" Name="[VD]" />
</iis:WebVirtualDir>
<CreateFolder/>
<!-- Need to have to ensure created -->
</Component>
<Component Id="EnableASPNet4Extension" Permanent="yes" Guid="73FA6E54-2B0C-4AA7-A2A0-BDD432FECC62">
<CreateFolder/>
</Component>
<Component Id="PersistWebSiteValues" Guid="F249ADCB-B638-4E2B-9350-0421CEC5A803">
<RegistryKey Action="create" Root="HKLM" Key="SOFTWARE\!(loc.CompanyName)\!(loc.VirtualDirectory)\Install">
<RegistryValue Name="WebSiteDescription" Type="string" Value="[WEBSITE_DESCRIPTION]"/>
<RegistryValue Name="WebSiteID" Type="string" Value="[WEBSITE_ID]"/>
<RegistryValue Name="WebSitePath" Type="string" Value="[WEBSITE_PATH]"/>
<RegistryValue Name="WebSiteVD" Type="string" Value="[VD]"/>
<RegistryValue Name="WebSiteAppPoolName" Type="string" Value="[APP_POOL_NAME]"/>
</RegistryKey>
</Component>
</Directory>
</Directory>
</Directory>
</Directory>
<iis:WebSite Id='SelectedWebSite' Description='[WEBSITE_DESCRIPTION]' Directory='INSTALLLOCATION' SiteId='[WEBSITE_ID]'>
<!-- This element has to be here or WiX does not compile. -->
<iis:WebAddress Id="AllUnassigned" Port="80"/>
</iis:WebSite>
<!-- Define our custom actions -->
<Binary Id="IISCA" SourceFile="$(var.IISCA.TargetDir)$(var.IISCA.TargetName).CA.dll" />
<CustomAction Id="GetIISWebSites" BinaryKey="IISCA" DllEntry="GetWebSites" Execute="immediate" Return="check" />
<CustomAction Id="UpdatePropsWithSelectedWebSite" BinaryKey="IISCA" DllEntry="UpdatePropsWithSelectedWebSite" Execute="immediate" Return="check" />
<CustomAction Id="UpdateWebConfigFile" BinaryKey="IISCA" DllEntry="UpdateWebConfig" Execute="immediate" Return="check" />
<CustomAction Id="RegisterScriptMaps" BinaryKey="IISCA" DllEntry="RegisterScriptMaps" Execute="immediate" Return="check" />
<CustomAction Id="SetApplicationRootDirectory" Directory="INSTALLLOCATION" Value="[WEBSITE_PATH]\[VD]" />
<!-- Install UI Sequence - allows us to schedule custom action -->
<InstallUISequence>
<Custom Action="GetIISWebSites" After="CostFinalize" Overridable="yes">NOT Installed</Custom>
</InstallUISequence>
<InstallExecuteSequence>
<Custom Action="GetIISWebSites" After="CostFinalize" Overridable="yes">NOT Installed</Custom>
<Custom Action="UpdatePropsWithSelectedWebSite" After="GetIISWebSites">NOT Installed</Custom>
<Custom Action="SetApplicationRootDirectory" After="UpdatePropsWithSelectedWebSite">NOT Installed</Custom>
<Custom Action="UpdateWebConfigFile" After="InstallFinalize">NOT Installed</Custom>
<!--<Custom Action="UpdateWebAppMapping" After="InstallFinalize">NOT Installed</Custom>-->
<Custom Action="RegisterScriptMaps" After="InstallFinalize">NOT Installed</Custom>
</InstallExecuteSequence>
<Feature Id="ProductFeature" Title="!(loc.ProductName)" Level="1">
<ComponentRef Id='WebVirtualDirComponent' />
<ComponentRef Id='EnableASPNet4Extension'/>
<!--<ComponentGroupRef Id="WebSecurity.Web_Project" />-->
<ComponentGroupRef Id="Product.Generated" />
<ComponentRef Id="PersistWebSiteValues" />
</Feature>
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLLOCATION"/>
<UIRef Id="WixUI_WebUI" />
</Product>
</Wix>
Set the Package/#InstallScope attribute to perMachine. The default in Windows Installer is to create per-user packages.

Set WIXUI_INSTALLDIR to value from registry or default if that is blank?

I would like to be able to read a value from the registry and use it to set the WIXUI_INSTALLDIR before the dialog is displayed but if the value from the registry is blank I want to use a default folder.
I'm new to wix.
I've been reading tutorials, documentation, and questions/answers all day and my head is spinning. I think I'm close but I don't have all the pieces quite put together.
The code compiles and links fine but when I run the msi I get an error right before the browse for folder dialog is displayed the error is code 2819 "Control [3] on dialog [2] needs a property linked to it."
In summary what I want to do is:
Read previous install path from registry into a property named "PREVIOUSINSTALLFOLDER".
If "PREVIOUSINSTALLFOLDER" is blank, set WIXUI_INSTALLDIR to "INSTALLFOLDER" as defined in the Directory section.
If "PREVIOUSINSTALLFOLDER" is not blank set WIXUI_INSTALLDIR to "PREVIOUSINSTALLFOLDER".
What am I doing wrong?
Thanks,
Erik
Here's my current code:
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="EB907F6C-B193-4A40-BA3C-ADF8C069AF34" Name="LaserVault DMS" Language="1033" Version="10.0.0" Manufacturer="Electronic Storage Corp." UpgradeCode="43291cbc-3f74-44ba-ba14-31181bb654bf">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" Keywords="LaserVault DMS Server" Description="LaserVault DMS Server" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes" />
<UIRef Id="WixUI_InstallDir"/>
<Property Id="PREVIOUSINSTALLFOLDER">
<RegistrySearch Id="PreviousInstallDir" Root="HKLM" Key="Software\ESC" Name="LVDMSPath" Type="raw"></RegistrySearch>
</Property>
<CustomAction Id="SetToDefault" Property="WIXUI_INSTALLDIR" Value="[INSTALLFOLDER]" Execute="immediate" />
<CustomAction Id="SetToPrevious" Property="WIXUI_INSTALLDIR" Value="[PREVIOUSINSTALLFOLDER]" Execute="immediate" />
<InstallExecuteSequence>
<Custom Action="SetToDefault" After="AppSearch">PREVIOUSINSTALLDIR=""</Custom>
<Custom Action="SetToPrevious" After="AppSearch"><![CDATA[PREVIOUSINSTALLDIR <> ""]]></Custom>
</InstallExecuteSequence>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="LaserVault" Name="LaserVault">
<Directory Id="INSTALLFOLDER" Name="LVDMS" />
</Directory>
<Directory Id="ProgramMenuFolder" Name="Programs">
<Directory Id="ProgramMenuDir" Name="LaserVault DMS" />
</Directory>
<Directory Id="DesktopFolder" Name="Desktop" />
</Directory>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="LVDMSServerConfig" Guid="D9428A16-ECB1-4373-B876-8CF05E7CE37F">
<File Id="LVDMSServerConfig" Source="C:\Projects\LVDMS10\LVDMSServerConfig\LVDMSServerConfig\bin\Debug\LVDMSServerConfig.exe" KeyPath="yes" />
</Component>
<Component Id="LVDMSCore10" Guid="2E956300-78FC-4AFA-8D5D-A2D07B6CB8AE">
<File Id="LVDMSCore10" Source="C:\Projects\LVDMS10\LVDMSServerConfig\LVDMSServerConfig\bin\Debug\LVDMSCore10.dll" KeyPath="yes" />
</Component>
<Component Id="LVDMSInstallationGuide" Guid="ECA2B30A-54CB-4DE4-A659-B429458BDF3A">
<File Id="LVDMSInstallationGuide" Source="\\192.168.0.211\development\HelpFiles\LaserVault_DMS_10\LaserVault_DMS_Installation_Guide\LaserVault_DMS_Installation_Guide.pdf" KeyPath="yes" />
</Component>
</ComponentGroup>
<ComponentGroup Id="Shortcuts" Directory="ProgramMenuDir">
<Component Id="LVDMSServerConfigShortCut">
<Shortcut Id="LVDMSServerConfigShortCut" Name="LVDMS Server Config" Description="LaserVault DMS Server Configuration" Target="[#LVDMSServerConfig]" WorkingDirectory="INSTALLFOLDER" />
<RemoveFolder Id="ProgramMenuDir" On="uninstall"/>
<RegistryValue Root="HKCU" Key="Software\LaserVault\LVDMS" Name="CurrentVersion" Type="string" Value="[ProductVersion]" KeyPath="yes" />
</Component>
</ComponentGroup>
<ComponentGroup Id="RegistryEntries">
<Component Id="RegistryLVDMSPath" Guid="9AE59D2B-EF16-4CAA-8A27-AA5BE00FAA07" Permanent="yes" Directory="TARGETDIR">
<RegistryKey Root="HKLM" Key="Software\ESC">
<RegistryValue Type="string" Name="LVDMSPath" Value="[INSTALLFOLDER]"/>
</RegistryKey>
</Component>
</ComponentGroup>
<Feature Id="Complete" Title="LaserVault DMS Server" Level="1">
<ComponentGroupRef Id="ProductComponents" />
<ComponentGroupRef Id="Shortcuts"/>
<ComponentGroupRef Id="RegistryEntries"/>
</Feature>
</Product>
For future reference it's enough to only have the following:
<!-- Determine the directory of a previous installation (if one exists) -->
<Property Id="INSTALLFOLDER">
<RegistrySearch Id="GetInstallDir" Type="raw" Root="HKLM" Key="Software\ESC" Name="LVDMSPath" />
</Property>
...
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLFOLDER" />
Neither of the custom actions are required.
I think you were on the right path. I solved it the following way (basically quite similar as you tried to, just the other way round, i.e. set the default value and overwrite it only if the value was found in the registry) using the following steps:
Set WIXUI_INSTALLDIR to the default value as defined by your directory structure:
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR" />
Do a RegistrySearch for your previous installation folder:
<Property Id="PREVIOUSINSTALLFOLDER">
<RegistrySearch Id="GetPreviousInstallFolder" Root="HKLM" Key="SOFTWARE\ESC" Name="LVDMSPath" Type="raw" />
</Property>
Set INSTALLDIR only if a value was found:
<CustomAction Id="SetINSTALLDIR" Property="INSTALLDIR" Value="[PREVIOUSINSTALLFOLDER]" Execute="firstSequence" />
...
<InstallExecuteSequence>
<Custom Action="SetINSTALLDIR" After="AppSearch">PREVIOUSINSTALLFOLDER</Custom>
</InstallExecuteSequence>
<InstallUISequence>
<Custom Action="SetINSTALLDIR" After="AppSearch">PREVIOUSINSTALLFOLDER</Custom>
</InstallUISequence>

Checking for .NET installed in WiX installer? Where to place the condition?

I need to check for .NET version 4.5 installed before proceeding with my installation. This is my .wxs file. I've placed the propertyref and condition under the tag. Why is this check is not working?
Even if .NET 4.5 is not present on the target system, the installation goes ahead anyway.
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*"
Name="SolidFire Hardware Provider"
Language="1033"
Version="1.0.0.0"
Manufacturer="SolidFire"
UpgradeCode="0c60967f-f184-4b8b-a96a-b1caa4a8879e">
<Package InstallerVersion="200"
Compressed="yes"
InstallScope="perMachine" />
<!--Media Id='2' Cabinet='provider.cab' EmbedCab='yes'/-->
<PropertyRef Id="NETFRAMEWORK45"/>
<Condition Message="This application requires .NET Framework 4.5. Please install the .NET Framework then run this installer again.">
<![CDATA[Installed OR NETFRAMEWORK45]]>
</Condition>
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab='yes'/>
<Feature Id="ProductFeature" Title="InstallProvider" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
<!-- IRef Id="WixUI_Minimal"/-->
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLFOLDER" ></Property>
<!--Property WixUIDialogBmp = "logo.bmp"></Property-->
<UIRef Id="WixUI_InstallDir"/>
<InstallExecuteSequence>
<Custom Action="RunInstallScript" After="InstallFiles" >NOT Installed</Custom>
</InstallExecuteSequence>
<InstallExecuteSequence>
<Custom Action='BeforeUninstall' Before='RemoveFiles'>REMOVE="ALL"</Custom>
</InstallExecuteSequence>
<CustomAction Id="RunInstallScript"
ExeCommand="cmd /c install-solidfireprovider.cmd"
Directory="INSTALLFOLDER"
Execute="deferred"
Return="check"/>
<CustomAction Id="BeforeUninstall"
ExeCommand="cmd /c uninstall-solidfireprovider.cmd"
Directory="INSTALLFOLDER"
Execute="deferred"
Return="check"/>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="solidfireinstall" />
</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. -->
<File Id="restinterfacedll.dll"
Source="..\vssprovider\x64\$(var.build)\RESTInterfacedll.dll"></File>
</Component>
<Component Id="vssdll">
<File Id="vsssolidfireprovider.dll"
Source="..\vssprovider\x64\$(var.build)\vsssolidfireprovider.dll"></File>
</Component>
<Component Id="installscript">
<File Id="installscript"
Source="install-solidfireprovider.cmd"></File>
</Component>
<Component Id="uninstallscript">
<File Id="uninstallscript"
Source="uninstall-solidfireprovider.cmd"></File>
</Component>
<Component Id="registerprovider">
<File Id="registerprovider"
Source="register_app.vbs"></File>
</Component>
<Component Id="vshadow">
<File Id="vshadow"
Source="vshadow.exe"></File>
</Component>
</ComponentGroup>
</Fragment>
</Wix>
That looks OK so you probably also need to:
"Add the -ext command line parameter when calling light.exe to include the WixNetfxExtension in the MSI linking process."

How upgrade "secondary" executable using Wix?

I have msi setup written in Wix 3. Nothing too fancy, couple executables + some registry manipulations.
We have 2 executables, the main application and watch dog application that is always running(it's started once user logs in).
I've released new version of our software, in wix we specify to upgrade without uninstalling first. When new version msi is ran, it upgrades main application but watchdog application is not upgraded(even if it's not running, so it's not "in-use" problem)
I pasted below my wxs file, hopefully you can help me spot the problem.
Thanks a lot in advance,
Jack
This is the wxs file:
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?include Properties.wxi?>
<Product Id="$(var.ProductCode)" Name="$(var.Title)" Language="1033" Version="$(var.ProductVersion)" Manufacturer="$(var.Manufacturer)" UpgradeCode="$(var.UpgradeCode)">
<Package Description="$(var.ProductName)" Comments="$(var.ProductName)" InstallerVersion="200" Compressed="yes" />
<Property Id="PREVIOUSVERSIONSINSTALLED" Secure="yes" />
<Upgrade Id="$(var.UpgradeCode)">
<UpgradeVersion OnlyDetect='yes' Property='NEWERFOUND' Minimum='$(var.ProductVersion)' IncludeMinimum='no' />
<UpgradeVersion OnlyDetect="no" Property="PREVIOUSFOUND" Minimum="0.0.0" IncludeMinimum="yes" Maximum="$(var.ProductVersion)" IncludeMaximum="no" />
</Upgrade>
<Media Id="1" Cabinet="product.cab" EmbedCab="yes" CompressionLevel="high"/>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder" Name="PFiles">
<Directory Id="ApplicationRootFolder" Name="$(var.ProductName)">
<Component Id="MyAppComponent" Guid="6657828D-0D3F-43A6-A2CB-375BFBB8A412">
<RemoveFolder Id="ApplicationRootFolder" On="uninstall" />
<File Id="MyAppMain" Name="MyApp.exe" Source="..\Release\MyApp.exe"/>
<File Id="FirstRunApp" Name="FirstRunApp.exe" Source="..\Release\FirstRunApp.exe"/>
<File Id="MyAppWatchDog" Name="MyAppWatchDog.exe" Source="..\Release\MyAppWatchDog.exe"/>
<!--File Id="CheckSniffer" Name="CheckSniffer.exe" Source="..\Release\CheckSniffer.exe"/-->
<File Id="License" Name="License.rtf" Source="License.rtf"/>
</Component>
</Directory>
</Directory>
<Directory Id="DesktopFolder" >
<Component Id="DesktopShortcuts" Guid="5567ED7E-03F8-4AB8-AFB5-F8074F4ED1B5">
<RegistryValue Id="RegShortcutDesktop" Root="HKCU" Key="Software\$(var.ProductName)" Name="DesktopSC" Value="1" Type="integer" KeyPath="yes" />
<Shortcut Id="DesktopShortcut" Name="$(var.ProductName)" Directory="DesktopFolder" Description="$(var.ProductName)" Target="[ApplicationRootFolder]$(var.Name).exe" Icon="Icon.exe" WorkingDirectory="ApplicationRootFolder" />
</Component>
</Directory>
<Directory Id="ProgramMenuFolder">
<Directory Id="ProjectMenuFolder" Name="$(var.ProductName)">
<Component Id="StartMenuShortcuts" Guid="5567ED7E-03F8-4AB8-AFB5-F8074F4ED1B4">
<RegistryValue Root="HKCU" Key="Software\$(var.ProductName)" Type="string" Value="[ApplicationRootFolder]" Name="InstallPath"/>
<RegistryValue Root="HKCU" Key="Software\Microsoft\Windows\CurrentVersion\Run" Type="string" Value="[#MyAppWatchDog]" Name="MyAppWatchdog"/>
<RegistryValue Root="HKCU" Key="Software\$(var.ProductName)" Type="string" Value="" />
<Shortcut Id="ProgramMenuShortcut" Name="$(var.ProductName)" Description="$(var.ProductName)" Target="[ApplicationRootFolder]$(var.Name).exe" Icon="Icon.exe" WorkingDirectory="ApplicationRootFolder" />
<Shortcut Id="UninstallProduct" Name="Uninstall" Description="Uninstalls the $(var.ProductName)" Target="[System64Folder]msiexec.exe" Arguments="/x {$(var.ProductCode)}" />
<RemoveFolder Id="ProgramMenuDir" On="uninstall" />
<RemoveRegistryKey Root="HKCU" Key="Software\$(var.ProductName)" Action="removeOnUninstall"/>
</Component>
</Directory>
</Directory>
</Directory>
<Feature Id="DefaultFeature" Title="$(var.Name)" Level="1">
<ComponentRef Id="MyAppComponent" />
<ComponentRef Id="StartMenuShortcuts" />
<ComponentRef Id="DesktopShortcuts" />
</Feature>
<Property Id="SEARCHWINPCAP">
<RegistrySearch Id="RegistrySearch" Root="HKLM" Key="SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\WinPcapInst" Name="VersionMajor" Type="raw"/>
</Property>
<Property Id="WIXUI_INSTALLDIR" Value="ApplicationRootFolder"/>
<Property Id="PRODUCTNAME" Value="$(var.ProductName)"/>
<!--Property Id="SNIFFER_CHECK_RESULT" Value="0"/-->
<WixVariable Id="WixUIBannerBmp" Value="logo.JPG" />
<WixVariable Id="WixUILicenseRtf" Value="License.rtf" />
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="Launch $(var.Title)" />
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOX" Value="1" />
<Property Id="WixShellExecTarget" Value="[#MyAppMain]" />
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />
<CustomAction Id="SetLaunchWatchDogTarget" Property="WixShellExecTarget" Value="[#MyAppWatchDog]" />
<CustomAction Id="LaunchWatchDog" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />
<Binary Id="BinBrowseForFile" SourceFile="tools\WinPcap_4_1_2.exe"/>
<CustomAction Id='LaunchWinPcapSetup' BinaryKey="BinBrowseForFile" ExeCommand="/Install" Execute="deferred" Impersonate="no" Return="check"/>
<CustomAction Id='NoDowngrade' Error='A later version of [ProductName] is already installed.'/>
<Property Id="CUSTOM_TITLE" Value="$(var.Title) Setup" />
<CustomAction Id='SetRepearTitle' Property='CUSTOM_TITLE' Value='Repair $(var.Title)'/>
<CustomAction Id='SetRemoveTitle' Property='CUSTOM_TITLE' Value='Remove $(var.Title)'/>
<!--debug-->
<Binary Id="BinCustomAction" SourceFile="bin\release\CustomActions.CA.dll"/>
<!--Binary Id="BinCheckSniffer" SourceFile="..\Release\CheckSniffer.exe"/-->
<Property Id="USER_GUID_PATH" Value="Software\Licenses"/>
<Property Id="USER_GUID" />
<Property Id="DUBUG_URL" Value="http://debug.myapp.com/service/"/>
<Property Id="DUBUG_STATE" Value="STARTED" />
<CustomAction Id='SendRequest' BinaryKey="BinCustomAction" DllEntry="SendRequest" Execute="immediate" Return="check" />
<CustomAction Id='SendRequest_WinPcap_Start' BinaryKey="BinCustomAction" DllEntry="SendRequest" Execute="immediate" Return="check" />
<CustomAction Id='SendRequest_WinPcap_Finish' BinaryKey="BinCustomAction" DllEntry="SendRequest" Execute="immediate" Return="check" />
<CustomAction Id='LicenseAgreement_Next' Property='DUBUG_STATE' Value='LICENSE_AGREED' />
<CustomAction Id='InstallDirDlg_Install' Property='DUBUG_STATE' Value='INSTALL' />
<CustomAction Id='Exit_Finish' Property='DUBUG_STATE' Value='FINISH' />
<CustomAction Id='WinPcap_Start' Property='DUBUG_STATE' Value='WINPCAP_STARTED' />
<CustomAction Id='WinPcap_Finish' Property='DUBUG_STATE' Value='WINPCAP_FINISHED' />
<CustomAction Id='Traffic_Failed' Property='DUBUG_STATE' Value='TRAFFIC_FAILED' />
<CustomAction Id='Traffic_Uninstalled' Property='DUBUG_STATE' Value='UNINSTALLED' />
<CustomAction Id='Shell_icacls' Directory='ApplicationRootFolder' ExeCommand='icacls FirstRunApp.exe /setintegritylevel Low' Return="ignore" Execute="commit" Impersonate="no"/>
<InstallExecuteSequence>
<Custom Action='NoDowngrade' After='FindRelatedProducts'>NEWERFOUND</Custom>
<Custom Action="WinPcap_Start" Before="SendRequest_WinPcap_Start" ><![CDATA[SEARCHWINPCAP < "4" AND NOT Installed]]></Custom>
<Custom Action="SendRequest_WinPcap_Start" Before="LaunchWinPcapSetup"><![CDATA[SEARCHWINPCAP < "4" AND NOT Installed]]></Custom>
<Custom Action="LaunchWinPcapSetup" Before="InstallFiles"><![CDATA[SEARCHWINPCAP < "4" AND NOT Installed]]></Custom>
<!-- disable currently Custom Action="CheckSniffer" Before="Shell_icacls">NOT Installed</Custom-->
<Custom Action="Shell_icacls" Before="InstallFinalize"><![CDATA[VersionNT >= 600 AND NOT Installed]]></Custom>
<!--Custom Action="Shell_RunWatchDog" After="InstallFinalize"><![CDATA[NOT Installed]]></Custom-->
<RemoveExistingProducts After="InstallFinalize"></RemoveExistingProducts>
<Custom Action="Traffic_Uninstalled" Before='SendRequest'>Installed AND NOT UPGRADINGPRODUCTCODE</Custom>
<Custom Action="SendRequest" After='InstallFinalize'>Installed AND NOT UPGRADINGPRODUCTCODE</Custom>
</InstallExecuteSequence>
<UI />
<UIRef Id="WixUI_Wizard" />
<PropertyRef Id="NETFRAMEWORK35" />
<Condition Message="This application requires .NET Framework 3.5 SP1.">Installed OR NETFRAMEWORK35</Condition>
<Icon Id="Icon.exe" SourceFile="..\MyApp\Resources\icon_main.ico" />
</Product>
</Wix>
The first thing that jumps at me from your Wix code is the fact that you are shipping all executables inside a single component but there is no KeyPath for the component. This is a very bad idea! It will definitely result in many servicing issues, such as the one you're experiencing with your watchdog.exe not updating.
Windows Installer considers a component the smallest installation unit. Furthermore, the Windows Installer will only look at the KeyPath to decide whether the component exists (or needs to be updated, etc.) Since the "MyAppComponent" has no keypath, the WI will default to using the Directory as your keypath. This means that during an upgrade, if WI finds your directory, it will assume the component is already installed and will not update any of the files in the component.
The rule of thumb to follow is that any .exe or .dll file must be the only file in the component, and it should also be the keypath for your component. I go as far as creating a component for each individual file in my setups, which will avoid many headaches in the future. Try replacing the MyAppComponent with these components instead:
<Directory Id="ApplicationRootFolder" Name="$(var.ProductName)">
<Component Id="MyApp.exe" Guid="INSERT_GUID_HERE">
<File Id="MyApp.exe" Name="MyApp.exe" Source="..\Release\MyApp.exe" KeyPath="yes"/>
</Component>
<Component Id="FirstRunApp.exe" Guid="INSERT_GUID_HERE">
<File Id="FirstRunApp.exe" Name="FirstRunApp.exe" Source="..\Release\FirstRunApp.exe" KeyPath="yes"/>
</Component>
<Component Id="MyAppWatchDog.exe" Guid="INSERT_GUID_HERE">
<File Id="MyAppWatchDog.exe" Name="MyAppWatchDog.exe" Source="..\Release\MyAppWatchDog.exe" KeyPath="yes"/>
</Component>
<Component Id="CheckSniffer.exe" Guid="INSERT_GUID_HERE">
<File Id="CheckSniffer.exe" Name="CheckSniffer.exe" Source="..\Release\CheckSniffer.exe" KeyPath="yes"/>
</Component>
<Component Id="License.rtf" Guid="INSERT_GUID_HERE">
<File Id="License.rtf" Name="License.rtf" Source="License.rtf" KeyPath="yes"/>
</Component>
</Directory>
This should resolve your updating issues. You may also want to conisder splitting your shortcut components into one shortcut per component, and setting an HKCU value as the keypath for each component.
Thanks to everyone trying to help.
#Cosmin Pirvu was the one with correct answer. We didn't update the version of watchdog application and thus it was not being installed.
Thank you