What I would like to do is show the installer user a list of the websites on their server and allow them to choose one (using the method described here: http://www.cmcrossroads.
Based on Cheeso's answer and updated custom action to use C# with Microsoft.Web.Administration rather than Javascript with WMI. Tested against IIS 8.5.
CustomActions.cs:
public class IISCustomActions
{
//*****************************************************************************
// Purpose: Custom action that enumerates the local websites, and stores their
// properties in the ListBox and AvailableWebSites tables.
// Effects: Fills the ListBox table and sets WEBSITE.
// Returns: MsiActionStatus.Ok if the custom action executes without error.
// MsiActionStatus.Abort if error.
//*****************************************************************************
[CustomAction]
public static ActionResult GetWebsites(Session session)
{
ActionResult result = ActionResult.Success;
session.Log("Begin GetWebSites");
try
{
var c = 1;
var listboxesView = session.Database.OpenView("SELECT * FROM ListBox");
listboxesView.Execute();
var iisManager = new ServerManager();
SiteCollection sites = iisManager.Sites;
string firstWebSite = String.Empty;
foreach (Site site in sites)
{
session.Log("Web site " + site.Name);
string itemKey = site.Name;
// Set the default selection if one isn't passed in from the command line
if (("Default Web Site" == itemKey) && String.IsNullOrEmpty(session["WEBSITE"]))
{
session["WEBSITE"] = itemKey;
}
// If this is the first item, store it's name so we can select it as the default selection
// if Default Web Site doesn't exist
if (1 == c)
{
firstWebSite = itemKey;
}
Record listboxItem = new Record(4);
listboxItem.SetString(1, "WEBSITE"); // Property to update
listboxItem.SetInteger(2, c++); // Display order
listboxItem.SetString(3, itemKey); // Key returned by the selection
listboxItem.SetString(4, site.Name); // Displayed in the UI
listboxesView.Modify(ViewModifyMode.InsertTemporary, listboxItem);
session.Log("website record (" + site.Name + ") id(" + site.Id + ")");
}
// They musn't have Default Web Site in their list of sites
if (String.IsNullOrEmpty(session["WEBSITE"]))
{
session["WEBSITE"] = firstWebSite;
}
listboxesView.Close();
}
catch (Exception ex)
{
session.Log(ex.Message);
result = ActionResult.Failure;
}
return result;
}
//*****************************************************************************
// Purpose: Custom action that copies the selected website's properties from the
// AvailableWebSites table to properties.
// Effects: Fills the IISROOT and WEBSITE_PORT
// properties.
// Returns: MsiActionStatus.Ok if the custom action executes without error.
// MsiActionStatus.Abort if error.
//*****************************************************************************
[CustomAction]
public static ActionResult UpdatePropsWithSelectedWebSite(Session session)
{
session.Log("Begin UpdatePropsWithSelectedWebSite");
ActionResult result = ActionResult.Success;
try
{
var selectedWebSiteId = session["WEBSITE"];
session.Log("selectedWebSiteId(" + selectedWebSiteId + ")");
var iisManager = new ServerManager();
Site site = iisManager.Sites[selectedWebSiteId];
session["WEBSITE_PORT"] = site.Bindings[0].EndPoint.Port.ToString();
session["IISROOT"] = site.Applications["/"].VirtualDirectories["/"].PhysicalPath;
session.Log("End UpdatePropsWithSelectedWebSite EXIT (Ok)");
}
catch (Exception ex)
{
session.Log(ex.Message);
result = ActionResult.Failure;
}
return result;
}
}
Register custom action like this:
The dialog wxs looks like:
Note the DoAction event in the Next button control. This runs the custom action to update properties using the selected website.
And then follow Dan's answer regarding use of SiteId="*' when applying changes.