Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>OP didn't ask, but in case someone is wondering, yes, You can do this in script, as well. This example populates a ListBox, not a ComboBox, but the idea is the same. </p> <pre><code>function EnumerateWebSites_CA() { try { LogMessage("function EnumerateWebSites_CA() ENTER"); var c = 1; var serverBindings, aBindings; var listboxesView = Session.Database.OpenView("SELECT * FROM ListBox"); listboxesView.Execute(); var record = Session.Installer.CreateRecord(4); record.StringData(1) = "WEBSITE"; // Property record.IntegerData(2) = c++; // display order record.StringData(3) = "Server"; // returned by the selection record.StringData(4) = "Server-wide"; // displayed in the UI listboxesView.Modify(MsiViewModify.InsertTemporary, record); // Create this table dynamically. We could also create this // custom table in the WiX .wxs file , but that's not necessary. var query = "CREATE TABLE AvailableWebSites " + "(Num INT NOT NULL, Name CHAR(64), Desc CHAR(64), Port CHAR(16) NOT NULL, IP CHAR(32), Hostname CHAR(80) PRIMARY KEY Num)"; var createCmd = Session.Database.OpenView(query); createCmd.Execute(); createCmd.Close(); LogMessage("Table 'AvailableWebSites' has been created"); var websitesView = Session.Database.OpenView("SELECT * FROM AvailableWebSites"); websitesView.Execute(); LogMessage("Query from Table 'AvailableWebSites' has returned"); // do a WMI query to get the list of Websites on the server var iis = GetObject("winmgmts://localhost/root/MicrosoftIISv2"); // See the metabase hierarchy diagram here: // http://msdn.microsoft.com/en-us/library/ms524661.aspx // http://msdn.microsoft.com/en-us/library/ms525545.aspx // list "virtual servers", which is the same as websites. query = "SELECT * FROM IIsWebServerSetting" // get the list of virtual servers var results = iis.ExecQuery(query); LogMessage("WMI Query completed."); LogMessage("WMI Query results : " + typeof results); for(var e = new Enumerator(results); !e.atEnd(); e.moveNext()) { var site = e.item(); // site.Name // W3SVC/1, W3SVC/12378398, etc // site.Name.substr(6) // 1, 12378398, etc // site.ServerComment) // "Default Web Site", "Site2", etc // site.ServerBindings(0).Port // 80, 8080, etc LogMessage("Web site " + site.Name); LogMessage("listbox record"); record = Session.Installer.CreateRecord(4); record.StringData(1) = "WEBSITE"; record.IntegerData(2) = c++; record.StringData(3) = site.Name.substr(6); // site.Name; record.StringData(4) = site.ServerComment + " (" + site.Name + ")"; listboxesView.Modify(MsiViewModify.InsertTemporary, record); LogMessage("websites record"); LogMessage("website(" + site.Name + ") name(" + site.ServerComment + ") port(" + site.ServerBindings(0).Port + ")"); record = Session.Installer.CreateRecord(6); record.IntegerData(1) = parseInt(site.Name.substr(6)); // WebSiteNo record.StringData(2) = site.Name; // name, like W3SVC/1 record.StringData(3) = site.ServerComment; // WebSiteDescription record.StringData(4) = site.ServerBindings(0).Port; // WebSitePort record.StringData(5) = site.ServerBindings(0).Ip; // WebSiteIP; maybe empty record.StringData(6) = site.ServerBindings(0).Hostname; // WebSiteHeader; maybe empty websitesView.Modify(MsiViewModify.InsertTemporary, record); } listboxesView.Close(); websitesView.Close(); LogMessage("function EnumerateWebSites_CA() EXIT"); } catch (exc1) { Session.Property("CA_EXCEPTION") = exc1.message ; LogException(exc1); return MsiActionStatus.Abort; } return MsiActionStatus.Ok; } </code></pre> <p>There are a few supporting methods: </p> <pre><code>var MsiViewModify = { Refresh : 0, Insert : 1, Update : 2, Assign : 3, Replace : 4, Merge : 5, Delete : 6, InsertTemporary : 7, // cannot permanently modify the MSI during install Validate : 8, ValidateNew : 9, ValidateField : 10, ValidateDelete : 11 }; // http://msdn.microsoft.com/en-us/library/sfw6660x(VS.85).aspx var Buttons = { OkOnly : 0, OkCancel : 1, AbortRetryIgnore : 2, YesNoCancel : 3 }; var Icons= { Critical : 16, Question : 32, Exclamation : 48, Information : 64 } var MsgKind = { Error : 0x01000000, Warning : 0x02000000, User : 0x03000000, Log : 0x04000000 }; // http://msdn.microsoft.com/en-us/library/aa371254(VS.85).aspx var MsiActionStatus = { None : 0, Ok : 1, // success Cancel : 2, Abort : 3, Retry : 4, // aka suspend? Ignore : 5 // skip remaining actions; this is not an error. }; // spool an informational message into the MSI log, if it is enabled. function LogMessage(msg) { var record = Session.Installer.CreateRecord(0); record.StringData(0) = "CustomActions: " + msg; Session.Message(MsgKind.Log, record); } // Pop a message box. also spool a message into the MSI log, if it is enabled. function LogException(exc) { var record = Session.Installer.CreateRecord(0); record.StringData(0) = "CustomActions: Exception: 0x" + decimalToHexString(exc.number) + " : " + exc.message; Session.Message(MsgKind.Error + Icons.Critical + Buttons.btnOkOnly, record); } function decimalToHexString(number) { if (number &lt; 0) number = 0xFFFFFFFF + number + 1; return number.toString(16).toUpperCase(); } </code></pre> <p>And yes, I disagree philosophically with <a href="http://blogs.msdn.com/robmen/archive/2004/05/20/136530.aspx" rel="nofollow noreferrer">Rob Mensching's viewpoint</a> that Script Custom Actions suck</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload