BradHards
BradHards

Reputation: 702

Decoupling Wix Component from ComponentGroup

I'm trying to generate Wix source from a custom Visual Studio extension. As such, I'd like to be able to (somehow) just add one file (plus project reference) to the Wix Project, and have the new DLLs added in to the Product.

As an example:

<Product Id="*" Name="blah" Version="..." Manufacturer="foo" UpgradeCode="...">
    <Package InstallerVersion="200" ... />

    <MajorUpgrade DowngradeErrorMessage="..." />
    <MediaTemplate EmbedCab="yes" />

        <Feature Id="ProductFeature" Title="blah" Level="1">
            <ComponentGroupRef Id="ProductComponents" />
        </Feature>
        <!-- Custom actions, Directories, etc .... -->
</Product>

Then in separate files (which I want to be generated), I have some Fragments:

<Fragment>
    <DirectoryRef Id="MYINSTALLDIR">
       <Component Id="CMP_FILE1" Guid="...">
         <File Id="FILE1" Source="file1.dll" Assembly=".net" KeyPath="yes" />
       </Component>
   </DirectoryRef>
</Fragment>

and

<Fragment>
    <DirectoryRef Id="MYINSTALLDIR">
       <Component Id="CMP_FILE2" Guid="...">
         <File Id="FILE2" Source="file2.dll" Assembly=".net" KeyPath="yes" />
       </Component>
   </DirectoryRef>
</Fragment>

So far so good. The problem is that I need to tie those together with something like:

<Fragment>
  <ComponentGroup Id="ProductComponents">
    <ComponentRef Id="CMP_FILE1" />
    <ComponentRef Id="CMP_FILE2" />
  </ComponentGroup>
</Fragment>

That works, but I don't want to do that, because it requires editing of the ComponentGroup when I want to add the next file.

So I want to try to localise the information into my added file. I can live with it always being part of the same Feature.

I tried adding the Feature attribute to Component element:

<Fragment>
    <DirectoryRef Id="MYINSTALLDIR">
       <Component Id="CMP_FILE1" Guid="..." Feature="ProductFeature">
         <File Id="FILE1" Source="file1.dll" Assembly=".net" KeyPath="yes" />
       </Component>
   </DirectoryRef>
</Fragment>

but that didn't seem to add the Component to the parent feature (empty Media table warning from Wix on build, and Orca confirmed it).

I also tried adding the ComponentGroup to each generated file, but of course I can't duplicate Id attributes, and unique Id just pushes the coupling problem up into Feature...

Is there a way to add a Component without editing the ComponentGroup?

Upvotes: 0

Views: 143

Answers (1)

Tom Blodget
Tom Blodget

Reputation: 20772

No. But you could generate (rather than edit) your ComponentGroup[@Id="ProductComponents"]. The file where it is defined can be "hidden" by generating it into the obj folder and dynamically adding it to the compile. This is effectively what HarvestDirectory and the other targets that call heat do.

While your extension is adding project references and files into the project, it can also add an MSBuild Include that defines a Target with BeforeTargets="Compile". That Target can do the generation and add the generated file to the Compile ItemGroup.

You just have to have a contract that the extension will use a particular ComponentGroup Id for this purpose. (Heat uses unique names for component and file ids to prevent conflicts. I suggest you do that too, especially for "hidden" source files.)

Upvotes: 1

Related Questions