Why does my WiX installer need an empty CreateFolder to conditionally update an Xml file?
Asked Answered
H

2

50

TL;DR: Why do I need an empty <CreateFolder/> element in this conditional component in order to make it work?

I'm putting together a simple WiX based installer for an in-house application. This installer needs to deploy a standard configuration file (a normal .NET .config file) and then customize it using properties passed to msiexec on the command line.

One of the customizations is to create a specific application setting only if the RUNTIME property has been defined. Here's the WiX component for that:

  <Component Id="C.Rbnz.Fsis.CollectionPeriodService.exe.config.runtime"
             Guid="*">
    <Condition>
      <![CDATA[RUNTIME]]>
    </Condition>

    <CreateFolder/>

    <util:XmlFile Id="X.Runtime.1"
                  Action="createElement"
                  ElementPath="/configuration/appSettings"
                  File="[#F.Rbnz.Fsis.CollectionPeriodService.exe.config]"
                  Name="add"
                  Sequence="2"/>

    <util:XmlFile Id="X.Runtime.2"
                  File="[#F.Rbnz.Fsis.CollectionPeriodService.exe.config]"
                  ElementPath="/configuration/appSettings/add[\[]not(@key)[\]]"
                  Action="setValue"
                  Name="key"
                  Value="RunTime"
                  Sequence="3"/>

    <util:XmlFile Id="X.Runtime.3"
                  File="[#F.Rbnz.Fsis.CollectionPeriodService.exe.config]"
                  ElementPath="/configuration/appSettings/add[\[]@key='RunTime'[\]]"
                  Action="setValue"
                  Name="value"
                  Value="[RUNTIME]"
                  Sequence="4"/>

  </Component>

This works just as I want - if RUNTIME is specified on the commandline for msiexec, the new element gets created; if not, nothing happens.

Why do I have to have the empty <CreateFolder/> within this component?

While I was trying to get this working, I found "Wix Condition Statement", which showed a working component, but doesn't explain why <CreateFolder/> is necessary.

Removing <CreateFolder/> gives me this error:

ICE18: KeyPath for Component: 'C.Rbnz.Fsis.CollectionPeriodService.exe.config.runtime' is Directory: 'INSTALLDIR'. The Directory/Component pair must be listed in the CreateFolders table.

which is, I'm sure, quite informative once you know what it means.

Himelman answered 3/9, 2012 at 1:28 Comment(0)
F
52

Every component has a key path; the most common is a file. Your component doesn't have a file or other key path, so WiX gives it the default of a directory. Windows Installer then comes along and says that components with directory key paths must ensure the directory is created, even if something else will do so. It's a silly rule with an easy fix.

Flange answered 3/9, 2012 at 2:14 Comment(4)
I understand part of this - the component requires a key path, by default it gets a directory, and the <CreateFolder/> is needed to make sure it works. But which directory is it, and where? Is this safe? Is this creating empty (debris) folders somewhere on the target machine as a part of the install? Is there a tidier way to do this?Himelman
It's whatever you're telling the component its parent directory is. Based on the error message, it's INSTALLDIR.Flange
@Bevan: A lacking CreateFolder entry in an empty component that is set to install to an empty folder with no other files in it, will trigger an exotic situation where the folder is removed by Windows Installer after launch (because it is empty) and then Windows Installer tries to put it back again on the next launch via an advertised shortcut (this triggers a keypath check). This nonsense repeats in an endless cycle. I just verified to test if this has been fixed in later versions of Windows Installer, but I still see the problem. A CreateFolder entry prevents this exotic self-repair problem.Lexicostatistics
@Bevan: Just for reference, this problem is the same as issue 2 in this summary of common self-repair problems: How do I avoid triggering MSI self-repair with my WiX / MSI package?.Lexicostatistics
T
22

You can use the parametre KeyPath="yes" in your component tag instead. Only if the 'INSTALLDIR' is the correct path for this component.

Tresatrescha answered 12/6, 2013 at 8:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.