Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
397 views
in Technique[技术] by (71.8m points)

wix - Features installed to different locations but referencing the same components

I have a product that consists of multiple features that can be installed to different locations e.g. Feature 1 is an executable installed in Program Files and Feature 2 is a website installed in wwwroot. However both Feature 1 and Feature 2 rely on many of the same dll's and hence require the components containing those dll's to be installed in 2 different locations depending on which Features are installed.

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

To provide a further complete example of what I am 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 however result in ONLY File1.txt being installed in

C:Program Files (x86)Acme

and ONLY File2.txt being installed in

_C:InetpubwwwrootAcmeWebsite_

One solution is to define the components twice such as:

<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 then what happens if we add a third feature that is to be installed in another location? Do we then have to redefine every component again? With over 100 components, managing duplicate components will become a big job.

Any suggestions?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You are seeing a limitation in the Windows Installer. A Component can only be installed once via an MSI. Each Component can only be installed to a single Directory. To have the contents of a Component installed to two different locations, you either have to create another Component with the same content or try to use the CopyFile element to duplicate the content.

Probably not what you wanted to hear but that is the way the Windows Installer works.

Fortunately, if you chose to go with option 1, then WiX toolset will only compress the duplicated content across the Components once. Smart cabbing rocks!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...