Here's my setup:
Compiling at .NET 4.0 (this cannot change)
Using WiX 3.7
Using the WiX Extended Bootstrapper Application extension
So I'm creating a bootstrapper installation project and though I've got it working, I feel like there is a much more clean and easy way to do it.
Basically, I need to have the user select which environment they wish to use when they install the product. To do this, I use the WiX Extended Bootstrapper Application extension to allow me to put some radio buttons on the first install screen.
Getting that all setup was fine, but then I realized that I don't know how to easily determine which radio button has been selected. So as I work around I just listed the MSI three times in the bundle and put install conditions on each one.
Is there a way to determine which radio button has been selected with just one property? (For example, when I pass the InstallFolder property to my MSI as seen in the code below.) And if there isn't a way to do this currently, is there a way for me to do this without adding my MSI three times to the bundle?
Here's my code (Notice how I list essentially the same MsiPackage three times):
<?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">
<?include Properties.wxi ?>
<Bundle Name="!(loc.Product.Name)" Version="$(var.Version)" Manufacturer="!(loc.Product.Manufacturer)" UpgradeCode="$(var.UpgradeCode)" Condition="VersionNT >= v5.1">
<BootstrapperApplicationRef Id="WixExtendedBootstrapperApplication.Hyperlink2License">
<bal:WixExtendedBootstrapperApplication SuppressRepair="yes" LicenseUrl="" ThemeFile="$(var.Bundle.ExtTheme.RadioBtns.Path)" LocalizationFile="$(var.Bundle.ExtTheme.RadioBtns.l10n.Path)" />
</BootstrapperApplicationRef>
<WixVariable Id="WixMbaPrereqPackageId" Value="Netfx4Full" />
<Variable Name="InstallFolder" Type="string" Value="$(var.InstallFolder.Value)" />
<Variable Name="RadioButton1" Type="numeric" Value="0" />
<Variable Name="RadioButton2" Type="numeric" Value="0" />
<Variable Name="RadioButton3" Type="numeric" Value="1" />
<Chain>
<!-- Other Package References Here -->
<MsiPackage Id="DBConnections_Dev"
SourceFile="$(var.MSI.Path)"
Visible="no"
Vital="yes"
InstallCondition="RadioButton1 = 1">
<MsiProperty Name="INSTALLFOLDER" Value="[InstallFolder]" />
<MsiProperty Name="SELECTED_ENV" Value="1" />
</MsiPackage>
<MsiPackage Id="DBConnections_Stage"
SourceFile="$(var.MSI.Path)"
Visible="no"
Vital="yes"
InstallCondition="RadioButton2 = 1">
<MsiProperty Name="INSTALLFOLDER" Value="[InstallFolder]" />
<MsiProperty Name="SELECTED_ENV" Value="2" />
</MsiPackage>
<MsiPackage Id="DBConnections_Prod"
SourceFile="$(var.MSI.Path)"
Visible="no"
Vital="yes"
InstallCondition="RadioButton3 = 1">
<MsiProperty Name="INSTALLFOLDER" Value="[InstallFolder]" />
<MsiProperty Name="SELECTED_ENV" Value="3" />
</MsiPackage>
</Chain>
</Bundle>
</Wix>
I also asked this question on the project's CodePlex site and the developer responded as follows (here is a link to the full discussion: http://wixextba.codeplex.com/discussions/432341):
This can now be done using the custom actions feature.
I've tested his response and found it to be correct! This functionality is available as of version 3.7.4791.32058. There is also an example included in the source code demonstrating how this is done. I've posted the pertinent code below:
Needed in Custom Action c++ code:
STDMETHODIMP OnPlanCustomAction()
{
...
if (SUCCEEDED(BalGetNumericVariable(L"RadioButton1", &llValue)) && llValue)
{
m_pEngine->SetVariableNumeric(L"RadioButton", 1);
BalExitOnFailure(hr, "Failed to set variable.");
}
else if (SUCCEEDED(BalGetNumericVariable(L"RadioButton2", &llValue)) && llValue)
{
m_pEngine->SetVariableNumeric(L"RadioButton", 2);
BalExitOnFailure(hr, "Failed to set variable.");
}
else if (SUCCEEDED(BalGetNumericVariable(L"RadioButton3", &llValue)) && llValue)
{
m_pEngine->SetVariableNumeric(L"RadioButton", 3);
BalExitOnFailure(hr, "Failed to set variable.");
}
else if (SUCCEEDED(BalGetNumericVariable(L"RadioButton4", &llValue)) && llValue)
{
m_pEngine->SetVariableNumeric(L"RadioButton", 4);
BalExitOnFailure(hr, "Failed to set variable.");
}
else
{
m_pEngine->SetVariableNumeric(L"RadioButton", 0);
BalExitOnFailure(hr, "Failed to set variable.");
}
...
Needed in WiX XML (from examples that come with downloaded DLL):
<Variable Name="RadioButton1" Type="numeric" Value="0" />
<Variable Name="RadioButton2" Type="numeric" Value="1" />
<Variable Name="RadioButton3" Type="numeric" Value="0" />
<Variable Name="RadioButton4" Type="numeric" Value="0" />
<Chain DisableSystemRestore="yes">
<PackageGroupRef Id="NetFx40Redist" />
<MsiPackage
Id="Setup"
Compressed="yes"
SourceFile="Setup.msi"
Vital="yes">
<MsiProperty Name="APPLICATIONFOLDER" Value="[InstallFolder]" />
<MsiProperty Name="RadioButton" Value="[RadioButton]" />
</MsiPackage>
</Chain>
Check out the links in the text for the original examples from which these code samples were taken. Hope this helps others in the future.
Related
I am creating a WIX bundle which calls an executable.
In that call I'm trying to pass the installfolder as an argument but for some reason this doesn't seem to work.
The bundle:
<?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="$(var.Department) $(var.ProductName)"
Version="!(bind.packageVersion.Database.CLI.Verify)"
Manufacturer="$(var.Company) $(var.Department)"
UpgradeCode="5fc4dc21-0202-4e28-b8a4-b87f972ae32e"
DisableRemove="yes"
DisableModify="yes"
IconSourceFile="Database.ico">
<util:RegistrySearchRef Id='VerifyDotnetVersion' />
<Variable Name="InstallFolder" Type="string" Value="c:\$(var.Company)"/>
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.HyperlinkLicense">
<!-- LicenseUrl intentionally empty. -->
<bal:WixStandardBootstrapperApplication LicenseUrl=""
LogoFile="Database.png"
SuppressOptionsUI="no"
SuppressRepair="yes"/>
</BootstrapperApplicationRef>
<Chain>
<PackageGroupRef Id="SqlServer2019ExpressLocalDB" />
<PackageGroupRef Id="Database.CLI"/>
</Chain>
</Bundle>
<Fragment>
<util:FileSearch Id='VerifyDotnetVersion'
Variable="DotnetVersion"
Path="dotnet.exe"
Result="version" />
<bal:Condition Message="This installer requires at least dotnet version 6.">
DotnetVersion >= v6
</bal:Condition>
</Fragment>
</Wix>
And the part that is calling the ExePackage:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Fragment>
<PackageGroup Id="Database.CLI">
<ExePackage Id="Database.CLI.Verify"
DisplayName="Check whether SqlLocalDb has been installed."
SourceFile="$(var.SourceFile)"
InstallCommand="verify"
UninstallCommand="remove"
Vital="yes"
Compressed="no"
PerMachine="yes"
Permanent="no">
<ExitCode Value="0" Behavior="success" />
<ExitCode Value="1" Behavior="error" />
<ExitCode Value="5" Behavior="error" />
<ExitCode Value="31" Behavior="error" />
<ExitCode Value="183" Behavior="success" />
<ExitCode Value="574" Behavior="error" />
<ExitCode Value="3010" Behavior="forceReboot" />
</ExePackage>
<ExePackage Id="Database.CLI.Attach"
DisplayName="Attach database to the SqlLocalDb instance."
SourceFile="$(var.SourceFile)"
InstallCommand="attach Target="[INSTALLFOLDER]\$(var.Department)\$(var.ProductName)""
Vital="yes"
Compressed="no"
PerMachine="yes">
<ExitCode Value="0" Behavior="success" />
<ExitCode Value="1" Behavior="error" />
<ExitCode Value="5" Behavior="error" />
<ExitCode Value="31" Behavior="error" />
<ExitCode Value="183" Behavior="success" />
<ExitCode Value="574" Behavior="error" />
<ExitCode Value="3010" Behavior="forceReboot" />
</ExePackage>
</PackageGroup>
</Fragment>
</Wix>
When I look in the logs I see as argument:
[7A60:546C][2022-06-16T16:44:15]i301: Applying execute package: Database.CLI.Attach, action: Install, path: C:\ProgramData\Package Cache\0FD93FB1FD9BBE5B46CC123351ECE9DBCEC54E9D\Database.CLI.exe, arguments: '"C:\ProgramData\Package Cache\0FD93FB1FD9BBE5B46CC123351ECE9DBCEC54E9D\Database.CLI.exe" attach Target="\Analytics\Database"'
But I'm missing the contents of the [INSTALLFOLDER] so what I expect should be something like Target="c:\temp\Analytics\Database".
What am I missing here?
p.s. Is it also possible to provide an INSTALLFOLDER when launching the setup-bundle for silent installs? Like Database.Setup.exe InstallLocation=c:\temp
Many thanks in advance.
Burn variables are case-sensitive, so use [InstallFolder], not [INSTALLFOLDER].
I have a bootstrapper WiX project which can run a x86 or x64 MSI, depending on CPU. It works well. I set the ShowFilesInUse to "yes" so WiX can optionally kill running app or require restart.
However, if the app is running, the dialog shows the app name always as just "A" instead of the actual app name.
Just "A" nothing else. In the Task Manager my running app clearly shows it has a name of "My App" or MyApp.exe.
I'm not sure what I'm missing here.
<?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">
<?include $(sys.CURRENTDIR)\..\MyApp\WIX_Version.wxi?>
<?include $(sys.CURRENTDIR)\..\WiXSetup x64\Variables.wxi?>
<Bundle Name="My App" Version="$(var.ProductVersion)" Manufacturer="My Company LLC" UpgradeCode="$(var.UpgradeCode)" AboutUrl="http://www.mywebsite.com/tools/MyApp" IconSourceFile="..\Graphics\ApplicationLogo.ico">
<Variable Name="InstallFolder" Type="string" Value="" />
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLargeLicense">
<bal:WixStandardBootstrapperApplication LicenseFile="..\MyApp\EULA.rtf" LogoFile="..\Graphics\InstallerLogo_64.png" ShowVersion="yes" ShowFilesInUse="yes" />
</BootstrapperApplicationRef>
<Chain>
<MsiPackage Id="x86" InstallCondition="NOT VersionNT64" SourceFile="$(var.WiXSetup x86.TargetDir)MyAppSetup_x86.msi">
<MsiProperty Name="INSTALLFOLDER" Value="[InstallFolder]" />
</MsiPackage>
<MsiPackage Id="x64" InstallCondition="VersionNT64" SourceFile="$(var.WiXSetup x64.TargetDir)MyAppSetup_x64.msi">
<MsiProperty Name="INSTALLFOLDER" Value="[InstallFolder]" />
</MsiPackage>
</Chain>
</Bundle>
</Wix>
Having trouble making a System DSN via Wix
here is my test code
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="TestProduct" Language="1033" Version="0.0.0.1" Manufacturer="WixEdit" UpgradeCode="*">
<Package Description="Test file in a Product" Comments="Simple test" InstallerVersion="200" Compressed="yes" />
<Media Id="1" Cabinet="simple.cab" EmbedCab="yes" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Component Id="C_PROD_DSN" Guid="*">
<ODBCDataSource Id="Prod_Dsn" Name="SomeName" Registration="machine" DriverName="ODBC Driver 11 for SQL Server">
<Property Id="Description" Value="Some Description" />
<Property Id="Database" Value="SomeDB" />
<Property Id="Language" Value="us_english" />
<Property Id="LastUser" Value="SomeUser" />
<Property Id="Driver" Value="C:\windows\system32\msodbcsql11.dll" />
</ODBCDataSource>
</Component>
</Directory>
<Feature Id="DefaultFeature" Title="Main Feature" Level="1">
<ComponentRef Id="C_PROD_DSN" />
</Feature>
<UI />
</Product>
</Wix>
Wix Edit compiles it just fine but when i run it I get
Error configuring ODBC data source: SomeName. ODBC error 6: Component not found in the registry. Verify that the file SomeName exists and that you can access it.
This is a DSN to a SQL DB not to a file.
I know I can make this work by just building up the Registry trees I need, I just like to try it using what should be the built in functionality for the task.
Can this be done using ODBCDataSource? (without Custom Actions, I just don't have time to write another one right now) or should I just cut my losses and do it with RegistryKey and RegistryValue?
I am trying to create a dual purpose MSI file using WiX. I have followed the instructions for WixUI_Advanced as well as the instructions for Single Package Authoring. This seems to work fine when I default to having a per user install by default (MSIINSTALLPERUSER = 1) and allow the user to select a per machine install. However setting it to install per machine by default (MSIINSTALLPERUSER empty) always results in a UAC prompt even when the user selects a per user install. The per user install is only writing a single file to a non admin directory and definitely does not require elevated privileges.
I have also tried following this guide which everyone seems to be using to do Single Package Authoring with WiX but the results are exactly the same. A UAC prompt appears if per machine is the default and per user is selected but not if per user is the default and per user is selected.
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="DE75C3B3-6398-4F25-9048-FB7EEE5F6EBF" Name="MyApp" Language="1033" Version="1.0.0" Manufacturer="Company" UpgradeCode="ED573078-CC3E-4299-9E04-043B1EDC08DB">
<Package InstallerVersion="500" Compressed="yes" />
<!--Single Package Authoring-->
<Property Id="MSIINSTALLPERUSER" Secure="yes" Value="{}"/>
<Property Id="ALLUSERS" Secure="yes" Value="2"/>
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes" CabinetTemplate="arc{0}" CompressionLevel="high"/>
<Feature Id="ProductFeature" Title="MyApp" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
<UI>
<UIRef Id="WixUI_Advanced" />
</UI>
<Property Id="ApplicationFolderName" Value="MyApp" />
<Property Id="WixAppFolder" Value="WixPerMachineFolder" />
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFiles64Folder" Name="PFiles">
<Directory Id="APPLICATIONFOLDER" Name="MyApp">
</Directory>
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="APPLICATIONFOLDER">
<Component Id="MyApp.exe" Guid="903EDAFD-F513-407D-85A0-D737013B9B57">
<File Id="MyApp.exe" Source="MyApp.exe" KeyPath="yes" Checksum="yes"/>
</Component>
</ComponentGroup>
</Fragment>
</Wix>
Looking through the install log I see the following entries:
Product not registered: beginning first-time install
PROPERTY CHANGE: Modifying ALLUSERS property. Its current value is '2'. Its new value: '1'.
PROPERTY CHANGE: Deleting MSIINSTALLPERUSER property. Its current value is '{}'.
...
Action: InstallScopeDlg. Dialog created
PROPERTY CHANGE: Modifying WixAppFolder property. Its current value is 'WixPerMachineFolder'. Its new value: 'WixPerUserFolder'.
PROPERTY CHANGE: Deleting ALLUSERS property. Its current value is '1'.
...
Product not registered: beginning first-time install
PROPERTY CHANGE: Deleting ALLUSERS property. Its current value is '2'.
PROPERTY CHANGE: Deleting MSIINSTALLPERUSER property. Its current value is '{}'.
Based on the install log I tried reintroducing the lines replaced in the modified WixUI file from this guide which update the ALLUSERS property as it seems as though this was being set to a value of 1 for the per user install which would explain the UAC prompt. Having both the following lines from the Russian blog and the original WixUI_Advanced does seem to work.
<Publish Dialog="InstallScopeDlg" Control="Next" Property="ALLUSERS" Value="{}" Order="2">
WixAppFolder = "WixPerUserFolder"
</Publish>
<Publish Dialog="InstallScopeDlg" Control="Next" Property="ALLUSERS" Value="1" Order="3">
WixAppFolder = "WixPerMachineFolder"
</Publish>
<Publish Dialog="InstallScopeDlg" Control="Next" Property="MSIINSTALLPERUSER" Value="1" Order="3">
WixAppFolder = "WixPerUserFolder"
</Publish>
<Publish Dialog="InstallScopeDlg" Control="Next" Property="MSIINSTALLPERUSER" Value="{}" Order="2">
WixAppFolder = "WixPerMachineFolder"
</Publish>
It seems as though both ALLUSERS and MSIINSTALLPERUSER needs to be set based on the user's choice to allow installation with no Administrator privileges when a per machine install is the default. I can't find anywhere else online to confirm my findings however.
There are three properties to control the default install scope when using WixUI_Advanced UI: 'ALLUSERS', 'Privileged' and 'MSIINSTALLPERUSER'.
The property 'WixAppFolder' will control which radio button is selected by default when 'advanced' button is clicked.
And there is a konwn bug of wix needs a workaround: https://github.com/wixtoolset/issues/issues/2376
In summary, the wix config can be:
Per user
<Property Id='WixAppFolder' Value='WixPerUserFolder' />
<Property Id='ALLUSERS' Value='2' />
<Property Id='Privileged' Value='0' />
<Property Id='MSIINSTALLPERUSER' Value='1' />
<UI>
<UIRef Id='WixUI_Advanced' />
<UIRef Id='WixUI_ErrorProgressText' />
<Publish Dialog='InstallScopeDlg' Control='Next' Property='MSIINSTALLPERUSER' Value='1' Order='3'>WixAppFolder = "WixPerUserFolder"
<Publish Dialog='InstallScopeDlg' Control='Next' Property='MSIINSTALLPERUSER' Value='{}' Order='2'>WixAppFolder = "WixPerMachineFolder"
<Publish Dialog='InstallScopeDlg' Control='Next' Event='DoAction' Value='WixSetDefaultPerMachineFolder' Order='3'>WixAppFolder = "WixPerMachineFolder"
<Publish Dialog='InstallScopeDlg' Control='Next' Event='DoAction' Value='WixSetDefaultPerUserFolder' Order='3'>WixAppFolder = "WixPerUserFolder"
</UI>
Per machine
<Property Id='WixAppFolder' Value='WixPerMachineFolder' />
<Property Id='ALLUSERS' Value='1' />
<Property Id='Privileged' Value='1' />
<Property Id='MSIINSTALLPERUSER' Value='0' />
<UI>
<UIRef Id='WixUI_Advanced' />
<UIRef Id='WixUI_ErrorProgressText' />
<Publish Dialog='InstallScopeDlg' Control='Next' Property='MSIINSTALLPERUSER' Value='1' Order='3'>WixAppFolder = "WixPerUserFolder"
<Publish Dialog='InstallScopeDlg' Control='Next' Property='MSIINSTALLPERUSER' Value='{}' Order='2'>WixAppFolder = "WixPerMachineFolder"
<Publish Dialog='InstallScopeDlg' Control='Next' Event='DoAction' Value='WixSetDefaultPerMachineFolder' Order='3'>WixAppFolder = "WixPerMachineFolder"
<Publish Dialog='InstallScopeDlg' Control='Next' Event='DoAction' Value='WixSetDefaultPerUserFolder' Order='3'>WixAppFolder = "WixPerUserFolder"
</UI>
BTW, I created a project to simplify the configuration of wix. Hope it can help: https://github.com/xinnj/WiXCover
How can I make a major upgrade to an installation set (MSI) built with WiX install into the same folder as the original installation?
The installation is correctly detected as an upgrade, but the directory selection screen is still shown and with the default value (not necessarily the current installation folder).
Do I have to do manual work like saving the installation folder in a registry key upon first installing and then read this key upon upgrade? If so, is there any example?
Or is there some easier way to achieve this in MSI or WiX?
As reference, I my current WiX file is below:
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2003/01/wi">
<Product Id="a2298d1d-ba60-4c4d-92e3-a77413f54a53"
Name="MyCompany Integration Framework 1.0.0"
Language="1033"
Version="1.0.0"
Manufacturer="MyCompany"
UpgradeCode="9071eacc-9b5a-48e3-bb90-8064d2b2c45d">
<!-- Package information -->
<Package Keywords="Installer"
Id="e85e6190-1cd4-49f5-8924-9da5fcb8aee8"
Description="Installs MyCompany Integration Framework 1.0.0"
Comments="Installs MyCompany Integration Framework 1.0.0"
InstallerVersion="100"
Compressed="yes" />
<Upgrade Id='9071eacc-9b5a-48e3-bb90-8064d2b2c45d'>
<UpgradeVersion Property="PATCHFOUND"
OnlyDetect="no"
Minimum="0.0.1"
IncludeMinimum="yes"
Maximum="1.0.0"
IncludeMaximum="yes"/>
</Upgrade>
<!-- Useless but necessary... -->
<Media Id="1" Cabinet="MyCompany.cab" EmbedCab="yes" />
<!-- Precondition: .NET 2 must be installed -->
<Condition Message='This setup requires the .NET Framework 2 or higher.'>
<![CDATA[MsiNetAssemblySupport >= "2.0.50727"]]>
</Condition>
<Directory Id="TARGETDIR"
Name="SourceDir">
<Directory Id="MyCompany"
Name="MyCompany">
<Directory Id="INSTALLDIR"
Name="Integrat"
LongName="MyCompany Integration Framework">
<Component Id="MyCompanyDllComponent"
Guid="4f362043-03a0-472d-a84f-896522ce7d2b"
DiskId="1">
<File Id="MyCompanyIntegrationDll"
Name="IbIntegr.dll"
src="..\Build\MyCompany.Integration.dll"
Vital="yes"
LongName="MyCompany.Integration.dll" />
<File Id="MyCompanyServiceModelDll"
Name="IbSerMod.dll"
src="..\Build\MyCompany.ServiceModel.dll"
Vital="yes"
LongName="MyCompany.ServiceModel.dll" />
</Component>
<!-- More components -->
</Directory>
</Directory>
</Directory>
<Feature Id="MyCompanyProductFeature"
Title='MyCompany Integration Framework'
Description='The complete package'
Display='expand'
Level="1"
InstallDefault='local'
ConfigurableDirectory="INSTALLDIR">
<ComponentRef Id="MyCompanyDllComponent" />
</Feature>
<!-- Task scheduler application. It has to be used as a property -->
<Property Id="finaltaskexe"
Value="MyCompany.Integration.Host.exe" />
<Property Id="WIXUI_INSTALLDIR"
Value="INSTALLDIR" />
<InstallExecuteSequence>
<!-- command must be executed: MyCompany.Integration.Host.exe /INITIALCONFIG parameters.xml -->
<Custom Action='PropertyAssign'
After='InstallFinalize'>NOT Installed AND NOT PATCHFOUND</Custom>
<Custom Action='LaunchFile'
After='InstallFinalize'>NOT Installed AND NOT PATCHFOUND</Custom>
<RemoveExistingProducts Before='CostInitialize' />
</InstallExecuteSequence>
<!-- execute comand -->
<CustomAction Id='PropertyAssign'
Property='PathProperty'
Value='[INSTALLDIR][finaltaskexe]' />
<CustomAction Id='LaunchFile'
Property='PathProperty'
ExeCommand='/INITIALCONFIG "[INSTALLDIR]parameters.xml"'
Return='asyncNoWait' />
<!-- User interface information -->
<UIRef Id="WixUI_InstallDir" />
<UIRef Id="WixUI_ErrorProgressText" />
</Product>
</Wix>
There's an example in the WiX tutorial: https://www.firegiant.com/wix/tutorial/getting-started/where-to-install/
<Property Id="INSTALLDIR">
<RegistrySearch Id='AcmeFoobarRegistry' Type='raw'
Root='HKLM' Key='Software\Acme\Foobar 1.0' Name='InstallDir' />
</Property>
Of course, you've got to set the registry key as part of the install too. Stick this inside a component that's part of the original install:
<RegistryKey
Key="Software\Software\Acme\Foobar 1.0"
Root="HKLM">
<RegistryValue Id="FoobarRegInstallDir"
Type="string"
Name="InstallDir"
Value="[INSTALLDIR]" />
</RegistryKey>
'Registry' is deprecated. Now that part of code should look like this:
<RegistryKey Id="FoobarRegRoot"
Action="createAndRemoveOnUninstall"
Key="Software\Software\Acme\Foobar 1.0"
Root="HKLM">
<RegistryValue Id="FoobarRegInstallDir"
Type="string"
Name="InstallDir"
Value="[INSTALLDIR]" />
</RegistryKey>
You don't really need to separate RegistryKey from RegistryValue in a simple case like this. Also, using HKMU instead of HKLM takes care of it whether you're doing a machine or user install.
<RegistryValue
Root="HKMU"
Key="Software\[Manufacturer]\[ProductName]"
Name="InstallDir"
Type="string"
Value="[INSTALLDIR]"
KeyPath="yes" />