Functions installed in different places, but referring to the same components

I have a product that consists of several functions that can be installed in different places, for example. Function 1 is the executable file installed in Program Files, and Feature 2 is the website installed in wwwroot. However, both Feature 1 and Feature 2 rely on many of the same DLLs and therefore require components containing these DLLs to be installed in two different places depending on which features are installed.

Is there a way to achieve this without defining each component twice?

To provide a more complete example of what I'm trying to achieve, the following complete wxs file can be compiled using:

> candle.exe Foobar.wxs

> light.exe -ext WixUIExtension Foobar.wixobj

> msiexec / i Foobar.msi

<?xml version='1.0' encoding='windows-1252'?> <Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'> <Product Name='Foobar 1.0' Id='E578DF12-DDE7-4BC2-82CD-FF11862862D5' UpgradeCode='90F09DD5-E01B-4652-8971-515997730195' Language='1033' Codepage='1252' Version='1.0.0' Manufacturer='Acme Ltd.'> <Package Id='*' Keywords='Installer' Description="Acme 1.0 Installer" InstallerVersion='100' Languages='1033' Compressed='yes' SummaryCodepage='1252' /> <Media Id='1' Cabinet='Sample.cab' EmbedCab='yes' DiskPrompt="CD-ROM #1" /> <Property Id='DiskPrompt' Value="Acme 1.0 Installation" /> <Directory Id='TARGETDIR' Name='SourceDir'> <!-- Directory 1 (Program Files) --> <Directory Id="ProgramFilesFolder" Name="PFiles"> <Directory Id="PROGRAM_INSTALLDIR" Name="Acme" /> </Directory> <!-- Directory 2 (wwwroot) --> <Directory Id="Inetpub" Name="Inetpub"> <Directory Id="wwwroot" Name="wwwroot"> <Directory Id="WEBSITE_INSTALLDIR" Name="AcmeWebSite" /> </Directory> </Directory> </Directory> <DirectoryRef Id='PROGRAM_INSTALLDIR'> <Component Id="Component1" Guid="79EC9E0B-8325-427B-A865-E1105CB16B62"> <File Id="File1" Name="File1.txt" Source="File1.txt" /> </Component> </DirectoryRef> <DirectoryRef Id='WEBSITE_INSTALLDIR'> <Component Id="Component2" Guid="702E6573-8FBC-4269-A58D-FD1157111F0F"> <File Id="File2" Name="File2.txt" Source="File2.txt" /> </Component> </DirectoryRef> <Feature Id="Feature.Program" Title="My Program" TypicalDefault="install" Level="1" ConfigurableDirectory="PROGRAM_INSTALLDIR" > <ComponentRef Id="Component1"/> <ComponentRef Id="Component2"/> </Feature> <Feature Id="Feature.Website" Title="My Website" TypicalDefault="install" Level="1" ConfigurableDirectory="WEBSITE_INSTALLDIR" > <ComponentRef Id="Component1"/> <ComponentRef Id="Component2"/> </Feature> <UIRef Id="WixUI_Mondo" /> <UIRef Id="WixUI_ErrorProgressText" /> </Product> </Wix> 

This will cause ONLY File1.txt to be installed in

C: \ Program Files (x86) \ Acme

and ONLY File2.txt installed in

_C: \ Inetpub \ Wwwroot \ AcmeWebsite _

One solution is to determine the components twice, for example:

 <DirectoryRef Id='PROGRAM_INSTALLDIR'> <Component Id="Component1" Guid="79EC9E0B-8325-427B-A865-E1105CB16B62"> <File Id="File1" Name="File1.txt" Source="File1.txt" /> </Component> <Component Id="Component2" Guid="702E6573-8FBC-4269-A58D-FD1157111F0F"> <File Id="File2" Name="File2.txt" Source="File2.txt" /> </Component> </DirectoryRef> <DirectoryRef Id='WEBSITE_INSTALLDIR'> <Component Id="Component1.Web" Guid="397E93AA-32FB-425A-A783-386E0CCA2357"> <File Id="File1.Web" Name="File1.txt" Source="File1.txt" /> </Component> <Component Id="Component2.Web" Guid="5C3AFF06-3623-4524-A90B-72B46DE5572A"> <File Id="File2.Web" Name="File2.txt" Source="File2.txt" /> </Component> </DirectoryRef> <Feature Id="Feature.Program" Title="My Program" TypicalDefault="install" Level="1" ConfigurableDirectory="PROGRAM_INSTALLDIR" > <ComponentRef Id="Component1"/> <ComponentRef Id="Component2"/> </Feature> <Feature Id="Feature.Website" Title="My Website" TypicalDefault="install" Level="1" ConfigurableDirectory="WEBSITE_INSTALLDIR" > <ComponentRef Id="Component1.Web"/> <ComponentRef Id="Component2.Web"/> </Feature> 

But what happens if we add a third function that will be installed elsewhere? Do we need to redefine all components again? With over 100 components, managing duplicate components will be a big job.

Any suggestions?

+8
wix wix3
source share
3 answers

You see the limitation in the Windows installer. A component can only be installed once through MSI. Each component can be installed in only one directory. To install the content of the component in two different places, you need to create another component with the same content or try to use the CopyFile element to duplicate the content.

This is probably not what you wanted to hear, but that is how the Windows installer works.

Fortunately, if you chose option 1, then the WiX toolkit will only compress duplicate content by Components once. Smart stones for stones!

+14
source share

I recommend creating a separate function containing only common components. It should not be installed by default. Then you can create a custom action that marks this function for installation only when one of your real functions is installed.

To mark the install function, you can use the MsiSetFeatureState function: http://msdn.microsoft.com/en-us/library/aa370387(VS.85).aspx

The user action that does this may be due to the functional action of your functions: http://msdn.microsoft.com/en-us/library/aa368561(VS.85).aspx

+1
source share

Features can reference a directory for the Browse function, but that only means something if the components use directories that are that directory or a child of this directory. Otherwise, the component will go to the specified directory. In other words, you can have INSTALLDIR for this function, and most components still have ANOTHERDIR (for example, [CommonFilesFolder] Company \ Shared for another component, and it will go there). Then this component can belong to several functions, and you will be fine.

0
source share

All Articles