How do I populate a ComboBox at install time in WiX?

谁都会走 提交于 2019-11-30 14:57:46

I don't use DTF (all natural C++ CustomActions for me) but Record's are 1 based. Have you tried shifting all of your SetRecord() calls over by one index?

Also, the .wxs code above seems to suggest that you are using "DUMMYPROPERTY" as the control Property for the ComboBox not "IIS_WEBSITENAME" like the .cs code is using.

This one is pretty old, however I had similar issue and would like to share what I've found, maybe this saves someone's time.

to Make sure ComboBox table is created use EnsureTable, ensure CA doesn't overwrite defined value:

<EnsureTable Id="ComboBox"/>
<Property Id="RS_INSTANCES" Secure="yes"/>
<CustomAction Id="GetRSintances" BinaryKey="JSCommon" Return="ignore"
              JScriptCall="GetRSintances" Execute="immediate" />

<InstallUISequence>
  <Custom Action="GetRSintances" After="AppSearch">
    <![CDATA[NOT Installed AND NOT RS_INSTANCES]]>
  </Custom>
</InstallUISequence>

<InstallExecuteSequence>
  <Custom Action="GetRSintances" After="AppSearch">
    <![CDATA[NOT Installed AND NOT RS_INSTANCES]]>
  </Custom>
</InstallExecuteSequence>

 <!-- UI part -->
 <Control Id="ComboBox1" Type="ComboBox" X="20" Y="160" Width="100" Height="20" Property="RS_INSTANCES" Sorted="yes" >
    <ComboBox Property="RS_INSTANCES">
      <!-- dynamicly filled during installation -->
    </ComboBox>
  </Control>

I have a JavaScript function for filling ListItems: (yes, I know some of you don't like JS for custom actions, but it still is convenient enough)

// Add ListItem to ComboBox or ListView at install time
function AddListItemToMSI(Property, Order, Value, Text, Table) {
  try {
    var controlView = Session.Database.OpenView("SELECT * FROM " + Table);
    controlView.Execute();

    var record = Session.Installer.CreateRecord(4);
    record.StringData(1) = Property;
    record.IntegerData(2) = Order;
    record.StringData(3) = Value;
    record.StringData(4) = Text;

    controlView.Modify(7, record);
    controlView.Close();
  }
  catch (err) {
    ShowMessage('Couldn\'t add ListItem entry, error occured: ' + err.message, msiMessageTypeInfo);
  }

  return 1;
}

I call it from my other function (it is called as custom action) like this:

var ComboBoxProperty = 'RS_INSTANCES';
var InstanceFullName;
for (i = 0; i < Names.length; i++) {
    InstanceFullName = GetInstanceName(Names[i]); //this function looks up full name in the registry
    AddListItemToMSI(ComboBoxProperty, i, InstanceFullName, '', 'ComboBox');
    if (i == 0) {
      Session.Property(ComboBoxProperty) = InstanceFullName;
    }
}

NOTE: I removed non-relevant pieces of code from last function to make it readable. P.S. always (I mean ALWAYS) use null, zero length and error checking, try/catch and ensure logging with something like this:

function ShowMessage(text, options) {
    if (options == null) {
        var options = msiMessageTypeUser;
    }
    var oRecord = Session.Installer.CreateRecord(1);
    oRecord.StringData(1) = text;
    var response = Session.Message(options, oRecord);
    oRecord.ClearData();
    oRecord = null;
    response = null;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!