Monday, October 20, 2008

Dynamic directories using WIX

The other morning I was thinking of making MSI’s through WIX, which installs files in different directories and drives(these directories/drives are configurable via .BAT files, during the installation process). One common thought that might come to one’s mind would be that, the drive name should be stored in the registry, else it would be an issue during un-installation process. We normally perform a registry search and retrieve the path names , and do the un-installation. However we can follow a better approach. For instance if I want a couple of files to be installed in C:\ and a couple of them installed in D:\ (these paths are passed by say, a BAT file) then I could simply use the following syntax in my WIX.

1. As a best practice, all Directories must be rooted in TARGETDIR. Which means I can include all my sub directory tags in TARGETDIR
<directory id="TARGETDIR" name="SourceDir"><directory id="MDF_ROOT_PATH" name="MdfDir>

2. We also need not remember the drive names by storing it in registry. Instead of assigning the values (via CustomAction tags), you can just use the Property names as Directories and the paths will be assigned directly.Hence the below lines of code can be avoided.
<customaction id="Assign_H_Root_Value" directory="MDF_ROOT_PATH"><customaction id="Assign_O_Root_Value" directory="LDF_ROOT_PATH">

<customaction id="Assign_H_Root_Value" directory="MDF_ROOT_PATH"><customaction id="Assign_O_Root_Value" directory="LDF_ROOT_PATH">3. Also we need not remember Directory path in registry, when we install components.So your code can look like this:<directory id="TARGETDIR" name="SourceDir">
<directory id="TARGETDIR" name="SourceDir"><directory id="PATH_A" name="MdfDir">
<directory id="PATH_B" name="LdfDir">
</directory>
<directoryref id="TARGETDIR"><directory id="SomeName">
<component…>
<component…>
</component…>
</component…>
<directoryref id="PATH_A">
<directory id="SomeName">
<component…>
<component…>
</component…>
</component…>
<directoryref id="PATH_B">
<directory id="SomeName">
<component…>
<component…>
</component…>
</component…>
<componentgroup…>
<componentref…>
<componentref…>
<componentref…>
</componentref…>

You will have to pass PATH_A and PATH_B via command line during installation(thus making them configurable). By using the above method we need not to pass PATH_A and PATH_B during un-installation (via say, .BAT file), though we didn’t store the same in the registry.The above method is especially useful, when installation is done using Octopus(by passing the values of the drive names). However Octopus does not allow values to be passed while un-installing. Hence, we store these values in registry and perform a registry search and uninstall. By using the above method, we can avoid storing the values in registry, and still perform the un-installation process.
</componentref…>
</componentref…>
</componentgroup…>
</directory>
</directoryref>
</directory>
</directoryref>
</directory>
</directoryref>
</directory>
</directory>
</directory>
</customaction>
</customaction>
</customaction>
</customaction>
</directory>