3

I've created a merge module following the instructions in the Getting Started Wix guide located at: http://wix.sourceforge.net/manual-wix2/authoring_merge_modules.htm.

Here is the merge module wxs:

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <Module Id="SomeRepositoryMergeModule" Language="1033" Version="1.0.0.0">
    <Package Id="f11e7321-a687-4d53-8be7-21a8ae0721a6" Manufacturer="SomeCompany Technologies" InstallerVersion="200" />

    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="ProgramFilesFolder">
          <Directory Id="MODULEINSTALLLOCATION" Name="Some Repository">
            <Component Id="ServicesHostWindowsService" Guid="257D1FAE-4AFF-4155-BDB8-D81F50E5862B">
              <File Id="ServicesHostInstallerExecutable" KeyPath="yes" DiskId="1" Name="WindowsServiceHost.exe" Source="..\WindowsServiceHost\bin\Output_For_Installer\WindowsServiceHost.exe" />
              <File Id="ServicesHostConfig" KeyPath="no" DiskId="1" Name="WindowsServiceHost.exe.config" Source="..\WindowsServiceHost\bin\Output_For_Installer\WindowsServiceHost.exe.config" />
              <File Id="SomeCompanyCommon" KeyPath="no" DiskId="1" Name="SomeCompany.Common.dll" Source="..\WindowsServiceHost\bin\Output_For_Installer\SomeCompany.Common.dll" />
              <File Id="SomeRepositorySqlScript" KeyPath="no" DiskId="1" Name="SomeRepository.sql" Source="..\..\..\..\..\DB\SomeRepository\SomeRepository.sql" />
              <File Id="LogConfigXml" KeyPath="no" DiskId="1" Name="log.config.xml" Source="..\WindowsService\log.config.xml" />
              <ServiceInstall Id="ServicesHostInstallElement" ErrorControl="normal" Start="auto" Type="ownProcess" Vital="yes"
                              Name="AServer WindowsService Host"
                              Description="The windows service responsible for hosting SomeCompany Some Repository's WindowsService."
                                                    />
              <ServiceControl Id="ServicesHostController" Name="AServer WindowsService Host" Remove="uninstall" Start="install" Stop="uninstall" Wait="no" />
            </Component>
          </Directory>
      </Directory>
    </Directory>
    <ComponentGroupRef Id="Product.Generated" /><!-- Harvested by heat -->
  </Module>  
</Wix>

And here is the main product wxs:

    <Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />

<Directory Id="TARGETDIR" Name="SourceDir">
  <Directory Id="ProgramFilesFolder">
    <Directory Id="SomeCompanyGlobalDir" Name="SomeCompany Technologies">
      <Directory Id="INSTALLLOCATION" Name="Some Repository">
        <Merge Id='SomeRepositoryPrimaryModule' Language='1033' SourceFile='..\SomeRepositoryMergeModule\bin\Output_For_Installer\SomeRepositoryMergeModule.msm' DiskId='1' />          
      </Directory>
    </Directory>
  </Directory>
</Directory>

<Feature Id="ProductFeature" Title="SomeRepositoryStandaloneInstaller" Level="1">           
  <!-- Note: The following ComponentGroupRef is required to pull in generated authoring from project references. -->            
  <MergeRef Id="SomeRepositoryPrimaryModule"/>
</Feature>

<UIRef Id="WixUI_InstallDir" />
<UIRef Id="WixUI_ErrorProgressText" />
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLLOCATION" />

When I build the installer and run it, the files from the merge module are not going into the directory selected by the user from within the installer UI. No matter what, they go into the "[Program Files]\SomeCompany Technologies\Some Repository\" directory.

If I remove the reference to Program Files from the merge module directory path and use a root dir with a name of "." to pick up the parent directory of the parent MSI then the merge module picks up the user selected directory just fine. But then Visual Studio throws an error on build that harvesting won't work because the path must be rooted in one of the standard directories in order to use automatically generated Guids.

So how can I get the merge module to take the directory selected by the user at install time while still keeping the merge module path rooted in a standard directory?

sirdank
  • 3,351
  • 3
  • 25
  • 58
Ayo I
  • 7,722
  • 5
  • 30
  • 40
  • Btw, I tried adding **ConfigurableDirectory** to the Feature tag with the value being INSTALLLOCATION, but it still doesn't pick up the directory... – Ayo I May 24 '12 at 19:06

1 Answers1

6

You are confusing MSI because ProgramFilesFolder is a reserved property name. Change that value to "MergeRedirectFolder" and by virtue of the Merge element under the Directory element with Id of INSTALLLOCATION MergeRedirectFolder will become associated with INSTALLLOCATION. The directory Some Repository ([MODULEINSTALLLOCATION]) will then be a subdirectory of INSTALLLOCATION.

Also feel free to checkout the ISWIX project on CodePlex. It's useful for authoring and maintaining merge modules and has sample source code relevant to what you are trying to do here.

Christopher Painter
  • 54,556
  • 6
  • 63
  • 100
  • Thank you for your response! So here is the problem. I'm using Visual Studio's heat harvesting integration. When I remove ProgramFilesFolder and replace it with MergeRedirectFolder I get the following error(s): The component 'cmpFBB3C43EFF7EC66E72A4BA7150FEFCD0' has a key file with path 'TARGETDIR\some_path\some_file.ext'. Since this path is not rooted in one of the standard directories (like ProgramFilesFolder), this component does not fit the criteria for having an automatically generated guid. How can I both: make your change and also continue to use built-in harvesting? – Ayo I Jun 01 '12 at 21:34
  • Nothing in this question has anything to do with harvesting. – Christopher Painter Jun 01 '12 at 21:41
  • True. But I am unable to apply your earlier solution because of the harvesting issue. I was trying to verify your solution and was unable because Visual Studio / heat seems to feel that replacing ProgramFilesFolder with MergeRedirectFolder now leaves the component unrooted in a standard directory. – Ayo I Jun 01 '12 at 22:08
  • The above answer does address the mapping of the installation directory at install time. However, for those trying to use Visual Studio's built-in harvesting, this solution may not work for you. I may open a follow-up question to try to address that half of the problem. – Ayo I Jun 05 '12 at 22:23
  • 2
    FWIW, I'm fundamentally opposed to "harvesting". There are just so many things that can go wrong when you ask a computer to figure out your dependencies and author them for you at build time rather then you doing it yourself and knowing it's only going to change when you want it to. – Christopher Painter Jun 05 '12 at 23:05
  • Thank you. Great response which was exactly what I needed. – Tom Beech Mar 26 '15 at 12:01
  • @user497745 Did you ever figure this out? Although I'm not harvesting, I'm encountering the same issue you describe in the comments. – sirdank Dec 22 '15 at 20:48
  • I still haven't used harvesting but perhaps this would help. I had to add `ComponentGuidGenerationSeed="{GUID-GOES-HERE}"` to my top level `` element. I'm sure I'll still have to change this at major upgrade time but changing one guid is better than changing 1000 because I've manually hardcoded every component to have a unique one. – sirdank Feb 17 '16 at 14:08