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:
- You must have a component. The name is irrelevant.
- You create a root
RegistryKey
, relative to which you can then create subkeys
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
- Add the option
-ext WixUtilExtension.dll
to bothcandle.exe
andlight.exe
. So,becomescandle.exe YOUR PROJECT NAME.wxs light.exe YOUR PROJECT NAME.wixobj
candle.exe -ext WixUtilExtension.dll YOUR PROJECT NAME.wxs light.exe -ext WixUtilExtension.dll YOUR PROJECT NAME.wixobj
- Change the header tag like this:
<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi' xmlns:util='http://schemas.microsoft.com/wix/UtilExtension'
- Add a
<util:PermissionEx
tag after theRegistryKey
. For examplegrants everyone read/write access to the key. For a full list of options, refer to http://wixtoolset.org/documentation/manual/v3/xsd/util/permissionex.html<util:Permissionx User='Everyone' GenericRead='yes' Read='yes' GenericWrite='yes' Write='yes'/>
- At this point you may repeat the question: why do I need
Id
andForceCreateOnInstall
tags for all of this? Well, because otherwiseWixUtilExtension.dll
will flag errors, simple as that...
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:
<RegistryValue Name='YOUR NAME' Value='YOUR VALUE' Type='string'/>
which should be obvious, and<RegistryValue Name='YOUR NAME' Value='YOUR VALUE' Type='integer'/>
.
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...