Wix installer does not overwrite previous version of an executable - wix

I have a very simple installer - copy a single dll to a Program Files subfolder and register it with regsvr32.exe. Works great, but if an older version of the dll is installed, "Repair" does not overwrite the existing dll. The dll is signed and its version (build) number is always incremented (e.g. 2.0.0.123 - > 2.0.0.124).
Looking at the previous similar posts, I added RemoveExistingProducts and specified ProductId as "*". Uninstalling and then installing the newer version works fine, but I really need Repair to update the existing dll.
Is there anything else I need to do?
Thank you!
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<!--
When creating a new install for the next version, these fields must be modified
-->
<?define ProductVersion = "2.0.00" ?>
<?define ProductId64 = "*" ?>
<?define ProductId32 = "*" ?>
<?define PackageId = "45F34788-66AC-441C-B666-707FFA7F1EE9" ?>
<!-- Product name as you want it to appear in Add/Remove Programs-->
<?if $(var.Platform) = x64 ?>
<?define ProductName = "XYZ (64 bit)" ?>
<?define Win64 = "yes" ?>
<?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>
<?define ProductId = "$(var.ProductId64)" ?>
<?define MainDllName = "XYZ64.dll" ?>
<?define MainDllSource = "..\..\bin\Win64\Release\XYZ64.dll" ?>
<?else ?>
<?define ProductName = "XYZ (32 bit)" ?>
<?define Win64 = "no" ?>
<?define PlatformProgramFilesFolder = "ProgramFilesFolder" ?>
<?define ProductId = "$(var.ProductId32)" ?>
<?define MainDllName = "XYZ.dll" ?>
<?define MainDllSource = "..\..\bin\Win32\Release\XYZ.dll" ?>
<?endif ?>
<?define UpgradeCode = "{C3763742-7C1C-4AB7-A404-F030B7550E97}" ?>
<Product Id="$(var.ProductId)" Name="$(var.ProductName)" Language="1033" Version="$(var.ProductVersion)" Manufacturer="Advanced Messaging Systems LLC" UpgradeCode="$(var.UpgradeCode)">
<Package Id="$(var.PackageId)" InstallerVersion="200" Compressed="yes" Description="XYZ Installer package" InstallPrivileges="elevated"/>
<!-- No restore point -->
<Property Id="MSIFASTINSTALL" Value="3" />
<Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="$(var.PlatformProgramFilesFolder)">
<Directory Id="INSTALLLOCATION" Name="XYZ">
<Component Id="XYZDll" Guid="E2CBEE41-6C0E-4A84-95C1-7282747B4A3D">
<File Id='MainDll' Name="$(var.MainDllName)" DiskId='1' Source="$(var.MainDllSource)" SelfRegCost="0" />
<!-- TODO: Insert files, registry keys, and other resources here. -->
</Component>
</Directory>
</Directory>
</Directory>
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLLOCATION" />
<!-- Note: Custom actions to install/uninstall the dll using regsvr32.exe -->
<CustomAction Id="RegisterDll"
Directory="INSTALLLOCATION"
ExeCommand='regsvr32.exe /s "[INSTALLLOCATION]$(var.MainDllName)"'
Return="check">
</CustomAction>
<CustomAction Id="UnregisterDll"
Directory="INSTALLLOCATION"
ExeCommand='regsvr32.exe /s /u "[INSTALLLOCATION]$(var.MainDllName)"'>
</CustomAction>
<Feature Id="ProductFeature" Title="XYZ" Level="1">
<ComponentRef Id="XYZDll" />
<!-- Note: The following ComponentGroupRef is required to pull in generated authoring from project references. -->
<ComponentGroupRef Id="Product.Generated" />
</Feature>
<InstallUISequence>
<Custom Action="WixCloseApplications" Before="AppSearch"/>
</InstallUISequence>
<InstallExecuteSequence>
<!-- Uninstall previous version before installing this one. -->
<RemoveExistingProducts Before="InstallInitialize"/>
<SelfRegModules/>
</InstallExecuteSequence>
<Icon Id="XYZ.ico" SourceFile="..\Graphics\XYZ.ico"/>
<Property Id="ARPPRODUCTICON" Value="XYZ.ico" />
<!-- UI -->
<UIRef Id="WixUI_InstallDir"/>
<UIRef Id="WixUI_ErrorProgressText" />
<WixVariable Id="WixUILicenseRtf" Value="..\EULA\license.rtf" />
<WixVariable Id="WixUIBannerBmp" Value="..\Graphics\banner.jpg" />
<WixVariable Id="WixUIDialogBmp" Value="..\Graphics\logo.jpg" />
<!-- End UI -->
</Product>
</Wix>
UPDATE. The following worked for me after modifying the upgrade entries:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<!--
When creating a new install for the next version, these fields must be modified
-->
<?define ProductVersion = "2.0.4" ?>
<?define ProductId64 = "*" ?>
<?define ProductId32 = "*" ?>
<?define PackageId = "*" ?>
<!-- Product name as you want it to appear in Add/Remove Programs-->
<?if $(var.Platform) = x64 ?>
<?define ProductName = "XYZ (64 bit)" ?>
<?define Win64 = "yes" ?>
<?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>
<?define ProductId = "$(var.ProductId64)" ?>
<?define MainDllName = "XYZ64.dll" ?>
<?define MainDllSource = "..\..\bin\Win64\Release\XYZ64.dll" ?>
<?else ?>
<?define ProductName = "XYZ (32 bit)" ?>
<?define Win64 = "no" ?>
<?define PlatformProgramFilesFolder = "ProgramFilesFolder" ?>
<?define ProductId = "$(var.ProductId32)" ?>
<?define MainDllName = "XYZ.dll" ?>
<?define MainDllSource = "..\..\bin\Win32\Release\XYZ.dll" ?>
<?endif ?>
<?define UpgradeCode = "{C3763742-7C1C-4AB7-A404-F030B7550E97}" ?>
<Product
Id="$(var.ProductId)"
Name="$(var.ProductName)"
Language="1033"
Version="$(var.ProductVersion)"
Manufacturer="Advanced Messaging Systems LLC"
UpgradeCode="$(var.UpgradeCode)"
>
<Package Id="$(var.PackageId)"
InstallerVersion="200"
Compressed="yes"
Description="XYZ Installer package"
InstallPrivileges="elevated"
/>
<!-- No restore point -->
<Property Id="MSIFASTINSTALL" Value="3" />
<Upgrade Id="$(var.UpgradeCode)">
<UpgradeVersion Minimum="1.0.0"
IncludeMinimum="yes"
OnlyDetect="no"
Maximum="$(var.ProductVersion)"
IncludeMaximum="no"
Property="PREVIOUSFOUND" />
</Upgrade>
<Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="$(var.PlatformProgramFilesFolder)">
<Directory Id="INSTALLLOCATION" Name="XYZ">
<Component Id="XYZDll" Guid="E2CBEE41-6C0E-4A84-95C1-7282747B4A3D">
<File Id='MainDll' Name="$(var.MainDllName)" DiskId='1' Source="$(var.MainDllSource)" SelfRegCost="0" />
<!-- TODO: Insert files, registry keys, and other resources here. -->
</Component>
</Directory>
</Directory>
</Directory>
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLLOCATION" />
<!-- Note: Custom actions to install/uninstall the dll using regsvr32.exe -->
<CustomAction Id="RegisterDll"
Directory="INSTALLLOCATION"
ExeCommand='regsvr32.exe /s "[INSTALLLOCATION]$(var.MainDllName)"'
Return="check">
</CustomAction>
<CustomAction Id="UnregisterDll"
Directory="INSTALLLOCATION"
ExeCommand='regsvr32.exe /s /u "[INSTALLLOCATION]$(var.MainDllName)"'>
</CustomAction>
<Feature Id="ProductFeature" Title="XYZ" Level="1">
<ComponentRef Id="XYZDll" />
<!-- Note: The following ComponentGroupRef is required to pull in generated authoring from project references. -->
<ComponentGroupRef Id="Product.Generated" />
</Feature>
<InstallUISequence>
<Custom Action="WixCloseApplications" Before="AppSearch"/>
</InstallUISequence>
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallInitialize"/>
<SelfRegModules/>
</InstallExecuteSequence>
<Icon Id="XYZ.ico" SourceFile="..\Graphics\XYZ.ico"/>
<Property Id="ARPPRODUCTICON" Value="XYZ.ico" />
<!-- UI -->
<UIRef Id="WixUI_InstallDir"/>
<UIRef Id="WixUI_ErrorProgressText" />
<WixVariable Id="WixUILicenseRtf" Value="..\EULA\license.rtf" />
<WixVariable Id="WixUIBannerBmp" Value="..\Graphics\banner.jpg" />
<WixVariable Id="WixUIDialogBmp" Value="..\Graphics\logo.jpg" />
<!-- End UI -->
</Product>
</Wix>

If you want a major uprade, start with the WiX MajorUpgrade element. The general rules for an upgrade are:
Different ProductCode and PackageCode from older product.
Increment ProductVersion somewhere in the first three fields.
Same UpgradeCode as older product.
Do something (like Wix MajorUprade or Upgrade elements) to ensure that you have an upgrade in place.
A per user install will not upgrade a per system install, or vice versa.
In your original case, failure to follow rules 1 and 2 meant that Windows thought the same product was already installed and went into Repair mode. That should have been your first warning because a major upgrade looks like a fresh install, not a repair. If you have two entries in Programs&Features it means that one or more of those 4 requirements has not been met. If you get "Another version of this product is already installed" it means you didn't follow rule 1, and variations in behavior are about ProductCode and PackageCode values compared with the installed product.

I am surprised that this line actually is allowed by the Wix compiler and linker:
<?define PackageId = "45F34788-66AC-441C-B666-707FFA7F1EE9" ?>
If this actually works and goes through, which I haven't tested, it means your package has a hard coded package id. I thought Wix featured protection against this problem? Perhaps it does? We should check with the Wix community if it ever makes any sense to allow hard coded package guid. I suppose it could be necessary for debugging and testing purposes - but there should at least be a compiler warning.
The idea of a package GUID is that it should be unique for each compiled MSI file. It is simply there to uniquely identify a file. Two different MSI files with the same package guid will be treated by Windows Installer as the same file by definition. All kinds of x-files problems result. Accordingly a package GUID should always be auto-generated since it is simply supposed to be unique. Please try to resolve this problem first to check if this solves your overall problem. Set it equal to *.
My advice is to auto-generate package id and product id but to set a hard coded upgrade code. An upgrade code identifies a "family of products" and is useful for identifying any instance of your product regardless of language and version. It might be useful to use a separate upgrade code for your 64 vs 32 bit setups since both versions can be installed at the same time on some systems.
You might also want to eliminate the use of regsvr32.exe for self-registration and extract COM data from your dll for proper MSI support: MSI register dll - Self-Registration considered harmful. And perhaps also check this: Register ActiveX exe server using WiX (check out RegSpy2 if Heat doesn't work).
Also note that you can leave out a lot of source attributes from your Wix xml file and rely on Wix defaults instead of hard coding values.
Some further details on GUIDs and file replacement:
Change my component GUID in wix?
MSI Reference Counting: Two products install the same MSIs
Forcing an upgrade of a file that is modified during its initial installation
msi version numbers
File Versioning Rules
Replacing existing files (diagram, both files have version)
Plain English file versioning description by Aaron Stebner

Short answer (the other one became too messy): try removing this line and let the package ID be auto generated by setting it to "*":
<?define PackageId = "45F34788-66AC-441C-B666-707FFA7F1EE9" ?>
Note that you must stop using all previous MSI builds after uninstalling them all. This is due to the faulty hard coded package guid which can cause unpredictable and unforeseen problems.

Related

Wix Toolset - upgrade and do not overwrite config file

I have an WPF app that connects to some web service on some URL. I have made an installation and it works like a charm, it even asks about URL and changes .config file as instructed. Now, I want to upgrade the app, but leave the .config file intact.
I have tried some solutions on web, it doesn't want to upgrade, it seems that only does a clean install every time.
<Package InstallerVersion="400" Compressed="yes" InstallScope="perMachine" Platform="x64" />
<Icon Id="icon.ico" SourceFile="$(var.ProjectDir)Icon.ico" />
<Property Id="ARPPRODUCTICON" Value="icon.ico" />
<WixVariable Id="WixUIBannerBmp" Value="Images\installer_top-banner.bmp" />
<WixVariable Id="WixUIDialogBmp" Value="Images\installer_background.bmp" />
<WixVariable Id="WixUILicenseRtf" Value="$(var.ProjectDir)\license.rtf" />
<Property Id="ARPURLINFOABOUT" Value="http://www.Company.com" />
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLFOLDER" />
<Property Id="FULLURL" Value="http://demo.Company.com/WcfFullPortal.svc" Secure="yes" />
<Property Id="AUTH" Value="0" Secure="yes" />
<Property Id="AUTHVALUE" Value="$(var.httpValue)" Secure="yes" />
<Property Id="PREVIOUSVERSIONSINSTALLED" Secure="yes" />
<Upgrade Id="1d96517a-8fc5-4150-b1cb-c3adf479a57d">
<UpgradeVersion Minimum="1.0.0.0" Maximum="99.0.0.0" Property="PREVIOUSVERSIONSINSTALLED" IncludeMinimum="yes" IncludeMaximum="no" />
</Upgrade>
<UIRef Id="SetupDialogUI" />
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="Launch MyApp" />
<Property Id="WixShellExecTarget" Value="[#MyApp.UI.WPF.exe]" />
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." AllowSameVersionUpgrades="yes" Schedule="afterInstallExecute" />
<MediaTemplate EmbedCab="yes" />
<!-- 32-bit / 64-bit variables -->
<?if $(var.Platform) = x64 ?>
<?define bitness = "(64 bit)" ?>
<?define Win64 = "yes" ?>
<?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>
<?else?>
<?define bitness = "(32 bit)" ?>
<?define Win64 = "no" ?>
<?define PlatformProgramFilesFolder = "ProgramFilesFolder" ?>
<?endif?>
<Condition Message="Minimum supported OS is Windows 7."><![CDATA[Installed OR (VersionNT >= 600)]]></Condition>
<!--
<?if $(var.Platform) = x64 ?>
<Condition Message="You need to install the 32-bit version of this product on 32-bit Windows.">
<![CDATA[VersionNT64]]>
</Condition>
<?endif?>
<?if $(var.Platform) = x86 ?>
<Condition Message="You need to install the 64-bit version of this product on 64-bit Windows.">
<![CDATA[NOT VersionNT64]]>
</Condition>
<?endif?> -->
</Product>
...
Two approaches:
Finish the work in the installer. MSI doesn't persist (remember) properties on subsequent insallations. You have to harvest the value from the config file back into the property so it can be shown in the UI again and reapplied during the installation.
http://robmensching.com/blog/posts/2010/5/2/the-wix-toolsets-remember-property-pattern/
Move the complexity out of the installer and into the application. Design the application so it asks for the setting on first run. Use the app.config appSettings element file attribute to specify a second file to contain the override setting. Have the installer create the app.config but not the second file. Have the application save the first run obtained setting to the second file. The installer doesn't know about this so it'll never touch the file during subsequent installs.
https://learn.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/appsettings/appsettings-element-for-configuration
I'm a WiX expert and can handle approach 1 easily. For people new to WiX it can be a challenge. I generally go with approach 1 when it's just a handful of settings and the program is non interactive like a windows service or say a web application where the inputs are pool identity. Otherwise I find it's easier for my customers to support if I move the complexity to code they better understand.

wix 3 installer: Unresolved bind-time variable !(bind.fileVersion.Name.exe)

I'm trying to use the binding "bind.fileVersion" from Wix3. (ie: 3.11.1)
For some me reason, I get the following error message:
Unresolved bind-time variable !(bind.fileVersion.TestWix3.exe).
My goal is to fill the 'Product Id' line. Especially the Version="$(var.VERSION)" information.
Here's the content of my "Product.wxs" file:
<?xml version="1.0" encoding="UTF-8"?>
<?define LongName = "Test wix 3" ?>
<?define Manufacturer = "Test" ?>
<?define ProductUpgradeCode = "5fc3e435-fad3-4c1d-997f-3483beffe0a4" ?>
<?define MAINEXE=$(var.TestWix3.TargetFileName)?>
<?define VERSION="!(bind.fileVersion.$(var.MAINEXE))"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="$(var.LongName)" Language="1036" Codepage="1252" Version="$(var.VERSION)" Manufacturer="$(var.Manufacturer)" UpgradeCode="$(var.ProductUpgradeCode)">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate />
<Feature Id="ProductFeature" Title="Wix3Installer" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="Wix3Installer" />
</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. -->
<!-- </Component> -->
</ComponentGroup>
</Fragment>
</Wix>
Here is the screenshot of my solution in VS2017 Community.
Here is the error:
Any idea why the binding of (bind.fileVersion) does not work ?
The FileId part of the bind variable is representing the <File Id="..."> Id. ie:
!(bind.fileVersion.TestWix3.exe)
...
<Component Id="MainProduct">
<File Id="TestWix3.exe" KeyPath="yes" Source="$(var.TestWix3.TargetPath)"/>
... other stuff maybe ...
</Component>
Currently your component and file definitions are TODO so you can't use this type of bind variable yet.
The syntax is !(bind.fileVersion.FileId) -- note the lowercase f.
Your define ?define MAINEXE=$(var.TestWix3.TargetFileName)?
translates to:
create a variable with Name MAINEXE and set it to the value of another variable.
There is no variable defined TestWix3.TargetFileName
Your second define created a variable with Name VERSION and uses the undefined MAINEXE
using the defines like this instead
?define MAINEXE=sample.exe?
?define VERSION="!(bind.fileVersion.$(var.MAINEXE))"?
compiles no problem
I ommitted the <&lt >&gt before and after ?
In our case (C++ program), this bind.FileVersion error message apparently was fixed by adding Win32 rc VERSIONINFO resources that were actually missing in the relevant library project (I'd think that WiX requires proper version declaration of a binary to e.g. make its installation/upgrade decisions etc.).

Wix error undefined preprocessor variable(error CNDL0150)

I am trying to build my first installer using WIX. I am not using visual studio instead i am using command line. I have a wxs file and i have also created a .wxi file for the Headers and i have defined them buy i get the following error when i run the candle.exe "Undefined preprocessor variable '$(var.ProjectDir)'"
Here is the .wxs and .wxi
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="{CB06C559-BCBF-4C85-95F3-FE55F6F50463}" Name="My first msi installer" Language="1033" Version="1.0.0.0" Manufacturer="Wave-axis" UpgradeCode="9be991bb-ceb1-4320-bfc7-56738e32c99a">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<Icon Id="icon.ico" SourceFile="$(var.ProjectDir)icon.ico" />
<Property Id="WAVEAXIS" Value="icon.ico" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate />
<UIRef Id="WixUI_Minimal" />
<!--used for the UI for the installer-->
<Feature Id="ProductFeature" Title="My first msi installer" Level="1">
<!-- This includes all the feature of the installer-->
<ComponentGroupRef Id="ProductComponents" />
<ComponentRef Id="ApplicationShortcut" />
<!--Used for shortcut on the start up menu-->
<ComponentRef Id="ApplicationShortcutDesktop" />
<!--used for desktop shortcut-->
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<!--install location of the application-->
<Directory Id="INSTALLFOLDER" Name="My first msi installer" />
</Directory>
<Directory Id="ProgramMenuFolder">
<!--install location for the startup-->
<Directory Id="ApplicationProgramsFolder" Name="My first msi installer" />
</Directory>
<Directory Id="DesktopFolder" Name="Desktop" />
<!--install loaction for the desktop-->
</Directory>
</Fragment>
</Wix>
.wxi code
<?xml version="1.0" encoding="utf-8"?>
<Include xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?define firstapplication.TargetDir ?>
<?define ProjectDir ?>
<?define firstapplication_TargetDir ?>
<?define ProductId=652648517 ?>
</Include>
regards Sagar
You need to include your wxi file in every wxs file you wish to use the properties in at the top of your file before the <Wix> tag
<?include $(sys.SOURCEFILEDIR)Path\to\InstallVars.wxi?>
<Wix xmlns="http://...">
...
</Wix>
This page will explain some of the available variables for the preprocessor like "SOURCEFILEDIR".

get "FileVersion" from a file that will not be installed

A well known trick to get a variable based on a file file version is
<?define ProductVersion = !(bind.FileVersion.filProductVersion) ?>
where
<Fragment>
<ComponentGroup Id="MyCG">
<Component Id="cmpabc" Directory="INSTALLDIR" Guid="YOUR-GUID-HERE">
<File Id="filProductVersion" KeyPath="yes" Source="$(var.MyRootFolder)\fileIAmGoingToInstall.dll" />
</Component>
Is there anyway to set a variable based on the file version of a file I do NOT want to install?
I've tried this:
MyWxs.wxs
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<Binary Id="binaryProductVersionId" SourceFile="$(var.MyRootFolder)\FileIDoNotWantToInstall.dll" />
</Fragment>
</Wix>
MyWxi.wxi
<?xml version="1.0" encoding="utf-8"?>
<Include>
<?define ProductVersion = !(bind.FileVersion.binaryProductVersionId) ?>
</Include>
But I get:
Severity Code Description Project File Line Suppression State
Error Unresolved bind-time variable !(bind.FileVersion.binaryProductVersionId).
You can try to place a condition inside the component that always be false.
<Component Id="cmpabc" Directory="INSTALLDIR" Guid="YOUR-GUID-HERE">
<File Id="filProductVersion" KeyPath="yes" Source="$(var.MyRootFolder)\fileIAmGoingToInstall.dll" />
<Condition>IGNORE = "0"</Condition>
</Component>
where IGNORE can be a property or use variable $(var.IGNORE)

wix installer platform dependency issues

I am trying to create one installer (one MSI file) for both x86 and x64. I would like the installation process to install only relevant files based on the target machine platform.
Till now I had one only MSI for x86 and it worked as expected.
Now I added this section:
<!-- Details to support both x86 and x64 platforms-->
<?if $(var.Platform) = x64 ?>
<?define ProductName = "MyApp (64 bit)" ?>
<?define Win64 = "yes" ?>
<?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>
<?define ExportReleaseComponentGroup = "Export64ReleaseComponentGroup" ?>
<?define MyApplication = "$(var.x64SourcePath)\MyApp.exe" ?>
<?else ?>
<?define ProductName = "MyApp" ?>
<?define Win64 = "no" ?>
<?define PlatformProgramFilesFolder = "ProgramFilesFolder" ?>
<?define ExportReleaseComponentGroup = "Export32ReleaseComponentGroup" ?>
<?define MyApplication = "$(var.win32SourcePath)\MyApp.exe" ?>
<?endif ?>
Now I get some errors:
In a x64 machine it is installed under Program Files (x86) folder. I am compiling the SetupProject in x86, can it be the reason for that? relevant code:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="$(var.PlatformProgramFilesFolder)">
The application does not run when installation ends. relevant code:
<!--CA to launch the exe after install-->
<Property Id="WixShellExecTarget" Value="$(var.MyApplication)" />
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />
A desktop shortcut and a start menu shortcut is not created. relevant code:
<Component Id="ProgramFilesShortcut" Guid="{My-Guid}">
<Condition>MY_DESKTOP_SHORTCUT</Condition>
<Shortcut Id="desktopMyApp" Directory="DesktopFolder" Name="MyApp" Target="$(var.MyApplication)" WorkingDirectory="bin" Icon="MyIcon.ico">
</Shortcut>
<RemoveFolder Id="ProgramFilesShortcut" On="uninstall" />
<RegistryValue Root="HKCU" Key="Software\[Manufacturer]\[ProductName]" Name="installed" Type="integer" Value="1" KeyPath="yes" />
</Component>
<Component Id="ProgramMenuDir" Guid="{My-Guid}">
<Shortcut Id="startmenuMyApp" Directory="ProgramMenuFolder" Name="MyApp" Target="$(var.MyApplication)" Icon="MyIcon.ico" WorkingDirectory="bin" Arguments="-s">
<!-- Set the AppID in order to get toasts to work -->
<ShortcutProperty Key="System.AppUserModel.ID" Value="MyCompany.MyApp" />
</Shortcut>
<RemoveFolder Id="ProgramMenuDir" On="uninstall" />
<RegistryValue Root="HKCU" Key="Software\[Manufacturer]\[ProductName]" Name="installed" Type="integer" Value="1" KeyPath="yes" />
</Component>
Any idea what am I doing wrong?
You are using compile-time variables so you are producing an MSI for either a 32-bit or a 64-bit installations. An MSI package must target either one or the other. In some cases, it doesn't matter but the design is to get components that do matter in the right place.
It could be possible to share the source between separate 32-bit and 64-bit builds.
Once you have the two MSI, you can use a WiX Bootstrapper project to bundle them and install the appropriate one on the target system.