在我的一个对话框中,我具有以下控件:

<Control Id="EnvironmentComboBox" Type="ComboBox" Sorted="yes" ComboList="yes" Property="ENVIRONMENT" X="25" Y="110" Width="200" Height="15" />

我将ComboBox填充到其他地方,如下所示:
<UI>
  <ComboBox Property="ENVIRONMENT">
    <ListItem Text="Development" Value="Development" />
    <ListItem Text="SIT" Value="SIT" />
    <ListItem Text="UAT" Value="UAT" />
    <ListItem Text="Production" Value="Production" />
  </ComboBox>
</UI>

但是,如果我没有创建ComboBox位,则MSI仍会生成,并且在安装期间会失败(2205)。因此,我想强制要求拥有一个名为ENVIRONMENT的属性。我尝试将如下所示的PropertyRef添加到我的对话框中:
<PropertyRef Id="ENVIRONMENT" />

但是,这似乎并没有实现<ComboBox Proeprty="ENVIRONMENT">。它将选择一个常规属性(<Property Id="ENVIRONMENT" Value="test" />),但这并没有太大帮助。

有什么方法需要定义ComboBox吗?

编辑:为了澄清起见,我打算将ComboBox定义与Control定义分开,以便可以重复使用对话框。

最佳答案

没有元素声明的属性声明的组合框项, MSI就可以存在(您可以在组合框文本字段中键入所需的任何文本,以防ComboList ='no')。

* 该元素在MSI表中没有任何对应的对象* (只有其子元素被写入MSI的ComboBox表中)。因此,我认为从WIX角度来看,此元素是完全可选的。

您的错误#2205是由所有中不存在'ComboBox'表引起的。我想您在安装程序中只有一个组合框。从理论上讲,不可能在编译时将其检测为错误(也可以在自定义操作中创建表)。 WIX团队最能做的就是发出警告。

为避免此错误,我在可重复使用的项目中声明了一个虚拟组合框元素:

  <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>

并从我常用的UI序列中引用了该UI。

现在,我无需担心任何安装程序中是否存在combobox表。

至于解决问题的变通方法-如何强制用户不要忘记声明列表项,我将使用 tepmlate wix文件代替wixlib 。像这样的东西:
<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>

并赋予用户使用您提供的模板转换工具重用此代码的唯一能力。它将验证是否为所有模板占位符提供了内容。

转换可能如下所示:
<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>

合并它们的工具:
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);
}

当然,该工具尚未发布-您可能希望向客户端添加一些有意义的错误消息,并验证提供的转换。但是为了避免代码复杂化,我没有实现这一点。

我目前在一些安装程序项目中使用这种方法。所有模板都存储在公共(public)位置,客户端安装程序可以获取所需的任何文件并进行转换。

我的发布工具当然要先进一些。它可以使用通配符替换属性中的值-我认为重用组件时非常有用。我使用这样的模板:
<Component Guid="{StrToGuid({ProductName}_7A51C3FD-CBE9-4EB1-8739-A8F45D46DCF5)}">

并且用户应在我的模板转换工具的命令行中提供所有模板属性(例如“ProductName”)。它可以确保组件在不同产品之间具有唯一的GUID,因此将它们安装在同一台计算机上时不会发生冲突。

注意:通过小心使用花括号-它们对于WIX和MSI具有特殊含义:http://msdn.microsoft.com/library/aa368609.aspx。但是对于我来说还不够清楚,我不经常使用它们。但是您可能需要另一个通配符前缀。

至于组织安装程序构建过程,您可以在项目的预构建中添加模板转换调用。但是我决定使用单独的构建脚本,而不是 native Visual Studio构建。它看起来更加简单和灵活。而且我不会收到诸如“以代码yyy退出的命令'xxx'”之类的讨厌错误-我总是看到模板转换日志,错误消息等。

希望我对轮子的重新发明可以对任何人有帮助=)。

关于combobox - PropertyRef需要ComboBox,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13345788/

10-14 16:36
查看更多