Creating Registry Settings with WiX

Overview

You can create registry entries in the .wxs source. If you have a lot of them (like I do), then one of the better options is to create the .wxs source from the registry; Otherwise if you have a properly maintained project (like I do not) then maybe you create registry keys / values automatically in the .wxs each time a new one is introduced during the build cycle. At any rate, the basic idea is this:

Example:

    <Component Id="RegistryEntries" Guid="YET ANOTHER GUID GOES HERE" KeyPath="yes">  
        <RegistryKey Root="HKLM" Key="SOFTWARE\p-nand-q.com\blablabla\whatever\you\get\the\idea" >
                ... subkeys ...
                ... registry values ...
        </RegistryKey>
    <Component>

Oh, don't forget to add this component with a ComponentRef to your Feature!

Creating subkeys

If you have subkeys, you just create them relative to their parent key, like this:

    <Component Id="RegistryEntries" Guid="YET ANOTHER GUID GOES HERE" KeyPath="yes">  
        <RegistryKey Root="HKLM" Key="SOFTWARE\p-nand-q.com\blablabla" >
            <RegistryKey Key='whatever'>
                <RegistryKey Key='you'>
                    <RegistryKey Key='get'>
                        <RegistryKey Key='the'>
                            <RegistryKey Key='idea'>
                                ... registry values ...
                            </RegistryKey>
                            ... registry values ...
                        </RegistryKey>
                        ... registry values ...
                    </RegistryKey>
                    ... registry values ...
                </RegistryKey>
                ... registry values ...
            </RegistryKey>
        </RegistryKey>
    <Component>

Actually, I recommend adding two tags Id and ForceCreateOnInstall to the RegistryKey keys, like this:

    <Component Id="RegistryEntries" Guid="YET ANOTHER GUID GOES HERE" KeyPath="yes">  
        <RegistryKey Root="HKLM" Key="SOFTWARE\p-nand-q.com\blablabla" >
            <RegistryKey Key='whatever' Id='Key1' ForceCreateOnInstall='yes'>
                <RegistryKey Key='you' Id='Key2' ForceCreateOnInstall='yes'>
                    <RegistryKey Key='get' Id='Key3' ForceCreateOnInstall='yes'>
                        <RegistryKey Key='the' Id='Key4' ForceCreateOnInstall='yes'>
                            <RegistryKey Key='idea' Id='Key5' ForceCreateOnInstall='yes'>
                                ... registry values ...
                            </RegistryKey>
                            ... registry values ...
                        </RegistryKey>
                        ... registry values ...
                    </RegistryKey>
                    ... registry values ...
                </RegistryKey>
                ... registry values ...
            </RegistryKey>
        </RegistryKey>
    <Component>

This looks stupid and superfluous, but it is required if you later want to set registry key permissions. So how do you do that?

Setting registry key permissions

At this point your build will succeed, but possibly your install fails: because the default install is not running with elevated privileges. To do so, edit the PAckage tag, like this:

    <Package Id='*' Keywords='Installer' Description="Acme's Foobar 1.0 Installer"
      Comments='Foobar is a registered trademark of Acme Ltd.' 
      Manufacturer='Wincor Nixdorf International GmbH'
      InstallPrivileges="elevated"
      InstallScope="perMachine"
      Platform="x86"
      InstallerVersion='100' Languages='1031' Compressed='yes' SummaryCodepage='1252' />

Adding values

All those keys and no values! Actually, values are fairly unexciting: they come in mostly two shapes:

So not a total challenge here... Refer to http://wixtoolset.org/documentation/manual/v3/xsd/wix/registryvalue.html for more options, but basically this is it...

However, to make things slightly more interesting, there is one thing you should know:

How to replace registry values with runtime variables

For example, you might want to write the installation directory into a registry value. You use ingeniously named Formatted Strings for that. In our example:

<RegistryValue Name='YOUR NAME' Value='[INSTALLDIR]' Type='string'/>

Will be replaced by the name of the directory with the Id INSTALLDIR. Obviously, this works for all other directories (and files) as well...