在WIX中,我需要一个点网管理的自定义代码,以使用该网络中的sql server实例的值动态填充组合框.
我试图谷歌,但没有任何工作
任何帮助是极大的赞赏.
[CustomAction] public static ActionResult FillServerInstances(Session xiSession) { xiSession.Log("Begin CustomAction"); xiSession.Log("Opening view"); View lView = xiSession.Database.OpenView("DELETE FROM ComboBox WHERE ComboBox.Property='DBSRVR'"); lView.Execute(); lView = xiSession.Database.OpenView("SELECT * FROM ComboBox"); lView.Execute(); int Index = 1; bool flag = false; try { foreach (DataRow dr in Microsoft.SqlServer.Management.Smo.SmoApplication.EnumAvailableSqlServers(false).Rows) { String InstanceName = dr["Name"].ToString(); if (InstanceName.Equals(xiSession["ComputerName"] + @"\" + xiSession["SQLINSTANCENAME"], StringComparison.InvariantCultureIgnoreCase)) { flag = true; } Record lRecord = xiSession.Database.CreateRecord(4); xiSession.Log("Setting record details"); lRecord.SetString(1, "DBSRVR"); lRecord.SetInteger(2, Index); lRecord.SetString(3, InstanceName); lRecord.SetString(4, InstanceName); xiSession.Log("Adding record"); lView.Modify(ViewModifyMode.InsertTemporary, lRecord); ++Index; } } catch (Exception ex) { logException(xiSession, ex); } if (flag) { xiSession["DBSRVR"] = xiSession["ComputerName"].ToString() + @"\" + xiSession["SQLINSTANCENAME"].ToString(); } lView.Close(); xiSession.Log("Closing view"); lView.Close(); return ActionResult.Success; }
OP没有问,但万一有人想知道,是的,你也可以用脚本来做.这个例子填充了ListBox,而不是ComboBox,但想法是一样的.
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; }
有一些支持方法:
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 < 0) number = 0xFFFFFFFF + number + 1; return number.toString(16).toUpperCase(); }
是的,我不同意Rob Mensching的观点,即Script Custom Actions很糟糕
在http://msiext.codeplex.com中有一个C++ CA可以做到这一点.