Install component only during fresh install but not during upgrade - wix

I have a component say web.config, in this component I have included a web.config file.
<Component Directory="FeatureA" Guid="{692AA53D-4DFB-4FA0-A6FD-D30905383D1D}" Id="web.config" Permanent="yes">
<File KeyPath="yes" Source="Content\web.config" />
</Component>
During upgrades, I dont want to install this component. So, I have added a condition
<Component Directory="FeatureA" Guid="{692AA53D-4DFB-4FA0-A6FD-D30905383D1D}" Id="web.config" Permanent="yes">
<Condition>[WixBundleInstalled]=0</Condition>
<File KeyPath="yes" Source="Content\web.config" />
</Component>
The above condition not working during upgrades. Component is installing during upgrades. What should I add inside condition, so that the component should not install during upgrades?

Related

Files not getting copied to install directory using WIX and WAX

I have some additional unmanaged dll's that need to be copied to the install folder. I am using WAX as well as it is supposed to make Wix easier to use. I have added the following markup to Product.wxs:
<Component Id="DataModel1.csdl" Guid="f8fb154d-f0c9-40f5-9bcf-593ed9540bda" Directory="INSTALLFOLDER">
<File Id="DataModel1.csdl" Name="DataModel1.csdl" Source="$(var.FLIR_TargetDir)DataModel1.csdl" />
</Component>
<Component Id="DataModel1.ssdl" Guid="a13c3c3b-e6a6-40ea-b9d8-84fd093ca0d5" Directory="INSTALLFOLDER">
<File Id="DataModel1.ssdl" Name="DataModel1.ssdl" Source="$(var.FLIR_TargetDir)DataModel1.ssdl" />
</Component>
<Component Id="DataModel1.msl" Guid="e308d75b-1f0b-4234-843d-6b44af2e80a9" Directory="INSTALLFOLDER">
<File Id="DataModel1.msl" Name="DataModel1.msl" Source="$(var.FLIR_TargetDir)" />
</Component>
<Component Id="Devart.Data.dll" Guid="a95a3053-7d4a-4030-b8c9-9d860a81a221" Directory="INSTALLFOLDER">
<File Id="Devart.Data.dll" Name="Devart.Data.dll" Assembly=".net" KeyPath="yes" Source="C:\Program Files (x86)\Devart\dotConnect\SQLite\Devart.Data.dll" />
</Component>
<Component Id="Devart.Data.SQLite.dll" Guid="16d0ca3c-425d-49e9-a754-043b0b9e4ada" Directory="INSTALLFOLDER">
<File Id="Devart.Data.SQLite.dll" Name="Devart.Data.SQLite.dll" Assembly=".net" KeyPath="yes" Source="C:\Program Files (x86)\Devart\dotConnect\SQLite\Devart.Data.SQLite.dll" />
</Component>
The files shows up as an unmapped file in the unmapped files area of the UI:
When the install happens the files do not get installed into the installation folder. What am I doing wrong?
The Assembly=".NET" tell's MSI to install the files in the Global Assembly Cache. The parent directory element is ignored/overridden. See:
http://wixtoolset.org/documentation/manual/v3/xsd/wix/file.html
If your looking for a tool to make WiX easier to learn/use then I'd suggest my own open source project:
https://github.com/iswix-llc/iswix-tutorials

The target file 'XXXX' is installed in 'YYYY' by two different components on an LFN system

We recently upgraded DevExpress. Since we have a custom theme, we had to upgrade the custom theme too.
That was the easy part. Now I'm trying to upgrade the setup to match the new file.
So basically, I'm changing the <File .../> of one <Component .../>:
From
<Component Id="Lib_Various_Files" Guid="9C621EB0-12E6-4D1D-8B5B-4150A76E33AA" KeyPath="yes" SharedDllRefCount="yes">
...
<File Id="DevExpress.Xpf.Themes.PreviousTheme.v17.1.dll" Name="DevExpress.Xpf.Themes.PreviousTheme.v17.1.dll" ReadOnly="yes" Vital="no" Compressed="default" DiskId="1" Source="$(var.DirLib)\PreviousTheme\DevExpress.Xpf.Themes.PreviousTheme.v17.1.dll" />
</Component>
To:
<Component Id="Lib_Various_Files" Guid="9C621EB0-12E6-4D1D-8B5B-4150A76E33AA" KeyPath="yes" SharedDllRefCount="yes">
...
<File Id="DevExpress.Xpf.Themes.OurTheme.v17.2.dll" Name="DevExpress.Xpf.Themes.OurTheme.v17.2.dll" ReadOnly="yes" Vital="no" Compressed="default" DiskId="1" Source="$(var.DirLib)\OurTheme\.td\Publish\DevExpress.Xpf.Themes.OurTheme.v17.2.dll" />
</Component>
Now I've an error in the setup, which seems to have no links to this line:
error LGHT0204: ICE30: The target file
'qgikh9i6.dll|System.Windows.Interactivity.dll' is installed in
'[TARGETDIR]\OurProduct\Bin\' by two different components on an LFN
system: 'cmpF5730C92213BA3272DDA3A5657DFF782' and 'Lib_Prism'. This
breaks component reference counting.
[D:\ws\OurProduct-Nightly\SetupWix\SetupWix\SetupWix.wixproj]
We do reference this library, in the Lib_Prism component(which is then in another Lib_Various component, that reference Lib_Prism and Lib_Various_Files, but nowhere else.
Any idea what could be the issue?
So here is the complete components list of this file:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<?include ..\Common.wxi?>
<DirectoryRef Id="BIN">
<Component Id="Lib_Various_Files" Guid="9C621EB0-12E6-4D1D-8B5B-4150A76E33AA" KeyPath="yes" SharedDllRefCount="yes">
...
<File Id="DevExpress.Xpf.Themes.OurTheme.v17.2.dll" Name="DevExpress.Xpf.Themes.OurTheme.v17.2.dll" ReadOnly="yes" Vital="no" Compressed="default" DiskId="1" Source="$(var.DirLib)\OurTheme\.td\Publish\DevExpress.Xpf.Themes.OurTheme.v17.2.dll" />
</Component>
<Component Id="Lib_MicrosoftPractices" Guid="780097FD-40C9-417A-A2C3-7C2B44567BEC" KeyPath="yes" SharedDllRefCount="yes">
<File ReadOnly="yes" DiskId="1" Source="$(var.DirPackages)\CommonServiceLocator.1.3\lib\portable-net4+sl5+netcore45+wpa81+wp8\Microsoft.Practices.ServiceLocation.dll" />
<File ReadOnly="yes" DiskId="1" Source="$(var.DirPackages)\Unity.4.0.1\lib\net45\Microsoft.Practices.Unity.Configuration.dll" />
<File ReadOnly="yes" DiskId="1" Source="$(var.DirPackages)\Unity.4.0.1\lib\net45\Microsoft.Practices.Unity.RegistrationByConvention.dll" />
<File ReadOnly="yes" DiskId="1" Source="$(var.DirPackages)\Unity.4.0.1\lib\net45\Microsoft.Practices.Unity.dll" />
</Component>
<Component Id="Lib_Prism" Guid="0F937515-2248-4CD2-B2E9-3E121FA9D743" KeyPath="yes" SharedDllRefCount="yes">
<File ReadOnly="yes" DiskId="1" Source="$(var.DirPackages)\Prism.Core.6.3.0\lib\net45\Prism.dll" />
<File ReadOnly="yes" DiskId="1" Source="$(var.DirPackages)\Prism.Unity.6.3.0\lib\net45\Prism.Unity.Wpf.dll" />
<File ReadOnly="yes" DiskId="1" Source="$(var.DirPackages)\Prism.Wpf.6.3.0\lib\net45\Prism.Wpf.dll" />
<File ReadOnly="yes" DiskId="1" Source="$(var.DirPackages)\Prism.Wpf.6.3.0\lib\net45\System.Windows.Interactivity.dll" />
</Component>
<Component Id="Lib_MvvmValidation" Guid="8681DBA1-F83D-475B-BCB8-A54A1F05FF0A" KeyPath="yes" SharedDllRefCount="yes">
<File ReadOnly="yes" DiskId="1" Source="$(var.DirPackages)\MvvmValidation.3.1.0\lib\netstandard1.0\MvvmValidation.dll" />
</Component>
<Component Id="Lib_Protobuf_Net" Guid="AEE6F4EB-78E3-4EC5-AA88-D5CC29D683D0" KeyPath="yes" SharedDllRefCount="yes">
<File ReadOnly="yes" DiskId="1" Source="$(var.DirDotfuscated)\ProtobufNet.dll" />
</Component>
</DirectoryRef>
<ComponentGroup Id="Lib_Various" >
<ComponentRef Id="Lib_MicrosoftPractices" />
<ComponentRef Id="Lib_Prism" />
<ComponentRef Id="Lib_Various_Files" />
<ComponentRef Id="Lib_MvvmValidation" />
<ComponentRef Id="Lib_Protobuf_Net" />
</ComponentGroup>
</Fragment>
</Wix>
Looking at your source file there are several problems with your component reference counting outright. You should never install several binaries with one component - it is a direct violation of the component rules. This causes exactly the kind of problems the error message indicates.
I recommend using a single file per component because that solves a plethora of possible reference count issues and upgrade problems. The shared-dll ref counters can also cause some blues I think. Do you have a legacy installer that you are trying to be compatible with? If not, then there is no reason to enable this component option - it increments the legacy SharedDLL ref-counter used by older, non-MSI installer technologies.
Now, for the issue where you change a file name in an existing component. This is also a violation of the component rules. You can not change the absolute file name of a component's key path and keep the same component GUID - this breaks component referencing. There must be a 1-to-1 correspondence between an absolute installation path and a component GUID.
The component GUID doesn't follow the file around if it moves, and the file "moves" when you change its file name (its absolute installation path has changed). There is an explanation here with an example: Change my component GUID in wix? (recommended read - decode this MSI peculiarity and things will be clearer going forward).
If you change a file name you can either:
Set your component GUIDs to auto-generate by deleting the whole GUID section in your source. The GUID will then be generated to be stable as long as the installation target path remains the same, and when you change the file name - for example - a new GUID will be generated for you auto-magically by WiX. See this answer for sample: Syntax for guids in WIX?
Set a new, hard-coded GUID yourself for the components where you change the file name that is being installed. This can be easy to forget - hence the recommended auto-magic described in point 1.
What you should actually do when file names change is to remove the old component and add a new one with the new file name. However, changing the GUID of an existing component and changing the file name has the same effect (same as deleting the old component and adding a new one).
With that said, there are bigger problems with this source as explained above. For future reliability you must split these components into one file per component. This causes interference between your old and new version and in order to clean this up, you can:
Set a totally new installation path for your project and use a single component per file from now on and you can use WiX's auto-magic component generation feature as explained above. This will work. Setting a new main installation folder "breaks the link" to "past component referencing sins".
Or you can uninstall the existing installation early during your major upgrade by moving RemoveExistingProducts early in the InstallExecuteSequence of your newest MSI version. This also wipes the slate clean of any component referencing issues and you can change your source to use one file per component going forward. If you use the MajorUpgrade element this change is easy - just set Schedule="afterInstallValidate". That should work (no time to test).
That should be it - if I have understood your scenario correctly.
Sample WiX extract for the proposed, new version:
<DirectoryRef Id="BIN">
<Component Feature="Product">
<File Source="$(var.DirLib)\OurTheme\.td\Publish\DevExpress.Xpf.Themes.OurTheme.v17.2.dll" />
</Component>
<Component Feature="Product">
<File Source="$(var.DirPackages)\CommonServiceLocator.1.3\lib\portable-net4+sl5+netcore45+wpa81+wp8\Microsoft.Practices.ServiceLocation.dll" />
</Component>
<Component Feature="Product">
<File Source="$(var.DirPackages)\Unity.4.0.1\lib\net45\Microsoft.Practices.Unity.Configuration.dll" />
</Component>
<Component Feature="Product">
<File Source="$(var.DirPackages)\Unity.4.0.1\lib\net45\Microsoft.Practices.Unity.RegistrationByConvention.dll" />
</Component>
<...>
</DirectoryRef>
Notice the tersified source with all attributes that can be auto-generated left out and all components now containing a single file. There is also direct specification of what feature each component belongs to as an attribute of the Component element. I find that this yields the least complicated and most flexible WiX source files. Preferences vary - obviously.
I would not roll with your current "multiple binaries per component" setup going forward. There will be more trouble if you do - almost guaranteed. MSI bites back - sorry to say - there are many bear traps. MSI has aspects that border on anti-patterns. The problems are faced by almost everyone. There is a section towards the bottom here on potential anti-patterns and also on the great benefits MSI yields for corporate deployment (just for reference): How to make better use of MSI files.
I am not particularly keen on this chaotic write-up of common MSI problems, but here it is: How do I avoid common design flaws in my WiX / MSI deployment solution? Maybe it can help to avoid some very common problems.
I finally found the issue:
It appears that DevExpress bin directory packs the System.Windows.Interactivity.dll library. So before we were not copying it and we didn't had it in our Lib\DevExpress folder.
It appears that we generate a componet with all Dll contained in the Lib\DevExpress folder, and therefore the System.WIndows.Interactivity.dll was contained in 2 differents packages.
I removed it from the DevExpress folder and now everything works fine. Sorry for the trouble.

Wix toolset Multiple Instances Installation

Some months ago I posted this question about multiple installation, and I strictly followed the example suggested me.
It worked very fine, but I try to remove the default Instance.
When I type
msiexec /x MyInstaller.msi
my App is "logically" removed, but no folders and no files are deleted on my machine!
Here is the code:
<Directory Id="TARGETDIR" Name="SourceDir">
<Component Id="comp_67F76B3C_8D92_4DCF_8C51_42E51502C4A3" Guid="28C71156-F612-49ED-A4E9-0CB598AA84AB" MultiInstance="yes">
<CreateFolder/>
</Component>
<Component Id="comp_AA102B27_0657_498D_9CD5_683C4F33B5E2" Guid="0F601C97-CDFF-4614-A608-B42253240E2C">
<File Id="_C72F9A1F_AF4A_47A3_928C_238643ABA5D4" Name="CrashReportManager.exe" Source="..\workspace\Release\CrashReportManager.exe" KeyPath="yes" />
</Component>
<Component Id="comp_442142FD_D0B8_410C_8904_E73047757FAB" Guid="0A1AE820-0FF7-442C-8333-9FEFA2E3F33C">
<File Id="_CA463C5C_E397_40E6_9B7B_28CCA647D0CA" Name="BCGCBPRO2440d120.dll" Source="..\workspace\Debug\BCGCBPRO2440d120.dll" KeyPath="yes" />
</Component>
<Directory Id="dir_350BD3EA_2F6C_4AD4_A960_8AB2C40F4F36" Name="Docs">
<Component Id="DocFolderId" Guid="32DAE480-7C01-4BAA-B99D-9FE8D7D43369" MultiInstance="yes">
<CreateFolder />
</Component>
<Component Id="comp_FFFDE3FE_1205_4E74_82B1_E832501A096C" Guid="EECC223C-EBAD-43CA-9F3C-4A19FD9E7429">
<File Id="_D0FE1868_D0D7_4778_8BC6_D40FE2B21DB2" Name="ModuleList(1).txt" Source="..\ModuleList(1).txt" KeyPath="yes" />
</Component>
<Component Id="comp_07E32598_CA8D_46B6_A3D6_DA36FD308E1F" Guid="FCCC41AA-17BC-4ADA-925D-631A614C9F80">
<File Id="_894CFDFB_4514_4CAC_86C3_426CC6836B7C" Name="ModuleList(2).txt" Source="..\ModuleList(2).txt" KeyPath="yes" />
</Component>
<Component Id="comp_21465088_A65C_43D4_A038_93412404BA91" Guid="67D18D29-6466-4D36-A279-A9396A62019C">
<File Id="_C9362477_88D8_463C_B77D_7097255F5E13" Name="ModuleList.txt" Source="..\ModuleList.txt" KeyPath="yes" />
</Component>
<Component Id="comp_3C85BB37_5715_45E7_A135_C640D7348360" Guid="6DDB0F88-7346-4221-8FB1-106C5F707EE5">
<File Id="_BFE55263_BD18_427B_9F87_30403BB2540D" Name="ReadMe.txt" Source="..\ReadMe.txt" KeyPath="yes" />
</Component>
</Directory>
</Directory>
What's wrong?
You used KeyPath="yes" in all of your components. This means, that such a component is used as a checkpoint for the Windows installer, for example if you want to repair an installation. It means that it is a mandatory component required for the application to function.
Since you are using multiple instances, and you mentioned you installed more than just the default instance, the Windows installer does not remove key components until the last one of the instances is getting uninstalled (i.e. it keeps track of them internally with a reference counter).
Use MultiInstance="yes" for each and every component, and like Yan says, get rid of the <CreateFolder/> component

Detect 64bit system from 32bit WIX installer

I have a 32bit WIX installer that installs a .NET based windows service. I need to use one external .dll that comes in 32bit and 64bit versions. Is there any way a 32bit installer can detect it's running on a 64bit machine? I want to then conditionally install the 32 or 64 bit .dll.
Extending Morten's answer, I did this in Wix 3.6
<Component Directory="INSTALLLOCATION">
<File Id="msvcp100.dll_x64" Source="$(var.x64)\msvcp100.dll" KeyPath="yes" />
<Condition><![CDATA[VersionNT64]]></Condition>
</Component>
<Component Directory="INSTALLLOCATION">
<File Id="msvcp100.dll_x86" Source="$(var.x86)\msvcp100.dll" KeyPath="yes" />
<Condition><![CDATA[Not VersionNT64]]></Condition>
</Component>
Try this:
<Component Id="Component1" Guid="*">
<![CDATA[Not VersionNT64]]>
<File Id="File1" Name="1.dll" Source="c:\dlls\1.dll"/>
</Component>
<Component Id="Component2" Guid="*">
<![CDATA[VersionNT64]]>
<File Id="File2" Name="2.dll" Source="c:\dlls\2.dll"/>
</Component>
Create a property with ProcessorArchitecture and get the value of this from registry. Based on this property create a CONDITIONAL FEATURE.

Wix major upgrade; need different behaviors for different components [duplicate]

This question already has an answer here:
WiX custom action with DTF... quite confused
(1 answer)
Closed 2 years ago.
Okay! I have finally more closely identified the problem I'm having. In my installer, I was attempting to get a settings file to remain intact on a major upgrade. I finally got this to work with the suggestion to set
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallFinalize" />
</InstallExecuteSequence>
This is successful in forcing this component to leave the original, not replacing it if it exists:
<Component Id="Settings" Guid="A3513208-4F12-4496-B609-197812B4A953" NeverOverwrite="yes">
<File Id="settingsXml" KeyPath="yes" ShortName="SETTINGS.XML" Name="Settings.xml" DiskId="1" Source="\\fileserver\Release\Pathways\Dependencies\Settings\settings.xml" Vital="yes" />
</Component>
However, this is a problem. I have another component listed here:
<Component Id="Database" Guid="1D8756EF-FD6C-49BC-8400-299492E8C65D" KeyPath="yes">
<File Id="pathwaysMdf" Name="Pathways.mdf" DiskId="1" Source="\\fileserver\Shared\Databases\Pathways\SystemDBs\Pathways.mdf" Vital="yes"/>
<File Id="pathwaysLdf" Name="Pathways_log.ldf" DiskId="1" Source="\\fileserver\Shared\Databases\Pathways\SystemDBs\Pathways.ldf" Vital="yes"/>
</Component>
And this component must be replaced on a major upgrade. I can only accomplish this so far by setting
<RemoveExistingProducts After="InstallInitialize" />
This breaks the first functionality I need with the settings file. How can I do both?
The problem is that settings.xml shouldn't be installed in the first place, what you really want to do is install something like a 'defaultSettings.xml' and have user-editable settings in a separate location, copying the default to the user/system config in either a post-install configuration step or at first run. If the user modifies the file, and runs a "repair" then it's going to get overwritten anyway, this is the intended behavior of Windows Installer.
If you really want Windows Installer to "leave the file alone" then you're going to need an unmanaged component, i.e. a component with an empty GUID. Such as...
<Component Id="Settings" Guid="" NeverOverwrite="yes">
<File Id="settingsXml" KeyPath="yes" ShortName="SETTINGS.XML" Name="Settings.xml" DiskId="1" Source="\\fileserver\Release\Pathways\Dependencies\Settings\settings.xml" Vital="yes" />
</Component>