MSI can exist without Combobox items declared for the property, referenced by a element (you have the ability to type any text you need in the combobox text field in case ComboList='no').
*The element doesn't have any corresponding object in the MSI tables* (only it's child elements gets written to the MSI's ComboBox table). So I suppose this element is completely optional from WIX point.
Your error #2205 is caused by non-existance of the 'ComboBox' table at all. I suppose you have only one combobox in the installer. Theoretically it is impossible possible to detect this at compile-time as error (tables can be created in custom actions as well). The most WIX team can do is generate warning.
To avoid this error I declared a dummy combobox element in my reusable project:
<Fragment><!--This fragment is intended to fill MSI tables with dummy items so that these tables became created. Tables without items aren't created-->
<UI Id="Dummy">
<Dialog Id="DummyDlg" Width="370" Height="270" Title="Dummy" NoMinimize="yes">
<Control Id="DummyDlgComboBox" Type="ComboBox" Property="DummyComboboxProperty" Width="200" Height="17" X="100" Y="80">
<ComboBox Property="DummyComboboxProperty">
<ListItem Text="Dummy" Value="Dummy" />
</ComboBox>
</Control>
</Dialog>
</UI>
</Fragment>
and referenced this UI from my commonly-used UI sequences.
Now I don't need to worry about existance of the combobox table in any of my installers.
As for a workaround to your problem - how to enforce users not to forget to declare list items, I would do a tepmlate wix file instead of the wixlib. Something like this:
<Control Id="EnvironmentComboBox" Type="ComboBox" Sorted="yes" ComboList="yes" Property="ENVIRONMENT" X="25" Y="110" Width="200" Height="15">
<ComboBox Property="ENVIRONMENT">
<Placeholder Id="EnvironmentComboBoxItems" />
</ComboBox>
</Combobox>
and give users the only ability to reuse this code using template transformation tool you provide. It will validate if all template placeholders are provided with content.
The transformation may look like this:
<TemplateSubstitutions>
<PlaceholderContent PlaceholderId='EnvironmentComboBoxItems'>
<ListItem Text="Development" Value="Development" />
<ListItem Text="SIT" Value="SIT" />
<ListItem Text="UAT" Value="UAT" />
<ListItem Text="Production" Value="Production" />
</PlaceholderContent>
</TemplateSubstitutions>
The tool for merging them:
static void Main(string[] args)
{
var templatePath = args[0];
var templateTransformPath = args[1];
var resultPath = args[2];
var templateDoc = XDocument.Load(templatePath);
var transformationDoc = XDocument.Parse(templateTransformPath);
Dictionary<string, XElement> contents = transformationDoc.Element("TemplateSubstitutions").Elements("PlaceholderContent").ToDictionary(e => e.Attribute("PlaceholderId").Value, e => e);
var planceHolders = templateDoc.Descendants("Placeholder").ToArray();
foreach (var ph in planceHolders)
{
ph.ReplaceWith(new XElement(contents[ph.Attribute("Id").Value]).Nodes());
}
templateDoc.Save(resultPath);
}
Of course this tool isn't release yet - you may want to add some meaningful error messages to your clients and validation of provided transformations. But to avoid code complication I didn't implement that.
I use this approach in few installer projects I have currently. All templates are stored in the common location and client installers can take any file they need and transform it.
My release tool is a bit more advanced of course. It can substitute values in the attributes using wildcards - I consider it extreemely useful when reusing components. I use then template like this:
<Component Guid="{StrToGuid({ProductName}_7A51C3FD-CBE9-4EB1-8739-A8F45D46DCF5)}">
and user should provide all template properties (such as 'ProductName') in command-line of my template transformation tool. It ensures components will have unique GUIDs between different products, so they will not conflict when installed on the same machine.
NOTE: Be careful with figure brackets though - they have special meaning for WIX and MSI: http://msdn.microsoft.com/library/aa368609.aspx. But as for me it is not clear enough and I don't use them regularly. But you might need another wildcard prefix.
As for organizing the installer build process, you can add template transformation calls on pre-build of the project. But I decided to use separate build scripts instead of native Visual studio build. It looks much more simple and flexible. And I don't get nasty errors like "command 'xxx' exited with code yyy" - I always see the template transformation log, error messages etc.
Hope my reinvention of the wheel will help anybody =).