#iis #combobox #wix #custom-action
#iis #поле со списком #wix #пользовательское действие
Вопрос:
Я следую ряду различных руководств в попытке создать универсальный установщик IIS WIX, который затем я могу соответствующим образом разделить на разные библиотеки.
Руководства
-
создание установщика веб-приложений с помощью wix 3.5 и Visual studio 2010 (блог Пола Рейнольдса)
-
Создание установщика WIX для ASP.NET Веб-приложение (проект кода)
Пока что у меня есть установка, которая, похоже, работает при запуске с флагом / q. Однако в интерактивном режиме пользовательское действие, которое должно заполнять поле со списком, не работает.
Я пытался выполнить отладку, но столкнулся со следующими проблемами:
- Сеанс.Команды журнала, похоже, нигде не выводятся
- Подключение к msiexec и вызов отладчика.Запуск или MmsiBreak, похоже, сразу завершаются (даже с включенными точками останова).
Начинаю расстраиваться, поскольку не должно быть так сложно принимать значения из пользовательского действия и передавать их в поле со списком.
У кого-нибудь есть идеи, что может быть основной причиной, я ожидаю, что многие люди либо использовали этот код, либо что-то похожее на него:
using System;
using System.Diagnostics;
using System.DirectoryServices;
using System.Globalization;
using System.Linq;
using Microsoft.Deployment.WindowsInstaller;
using Microsoft.Web.Administration;
using Microsoft.Win32;
namespace MyNameSpace
{
/// <summary>
/// Static class for the IIS Installer Custom Action.
/// </summary>
public static class CustomActions
{
#region Private Constants
private const string IISEntry = "IIS://localhost/W3SVC";
private const string SessionEntry = "WEBSITE";
private const string ServerComment = "ServerComment";
private const string CustomActionException = "CustomActionException: ";
private const string IISRegKey = @"SoftwareMicrosoftInetStp";
private const string MajorVersion = "MajorVersion";
private const string IISWebServer = "iiswebserver";
private const string GetComboContent = "select * from ComboBox";
private const string AvailableSites = "select * from AvailableWebSites";
private const string SpecificSite = "select * from AvailableWebSites where WebSiteID=";
#endregion
#region Custom Action Methods
[CustomAction]
public static ActionResult GetWebSites(Session session)
{
ActionResult result = ActionResult.Failure;
try
{
if (session == null) { throw new ArgumentNullException("session"); }
View comboBoxView = session.Database.OpenView(GetComboContent);
View availableWSView = session.Database.OpenView(AvailableSites);
if (IsIIS7Upwards)
{
GetWebSitesViaWebAdministration(comboBoxView, availableWSView);
}
else
{
GetWebSitesViaMetabase(comboBoxView, availableWSView);
}
result = ActionResult.Success;
}
catch (Exception ex)
{
if (session != null)
{
session.Log(CustomActionException ex);
}
}
return resu<
}
[CustomAction]
public static ActionResult UpdatePropsWithSelectedWebSite(Session session)
{
Debugger.Break();
ActionResult result = ActionResult.Failure;
try
{
if (session == null) { throw new ArgumentNullException("session"); }
string selectedWebSiteId = session[SessionEntry];
session.Log("CA: Found web site id: " selectedWebSiteId);
using (View availableWebSitesView = session.Database.OpenView(
SpecificSite selectedWebSiteId))
{
availableWebSitesView.Execute();
using (Record record = availableWebSitesView.Fetch())
{
if ((record[1].ToString()) == selectedWebSiteId)
{
session["WEBSITE_ID"] = selectedWebSiteId;
session["WEBSITE_DESCRIPTION"] = (string)record[2];
session["WEBSITE_PATH"] = (string)record[3];
}
}
}
result = ActionResult.Success;
}
catch (Exception ex)
{
if (session != null)
{
session.Log(CustomActionException ex);
}
}
return resu<
}
#endregion
#region Private Helper Methods
private static void GetWebSitesViaWebAdministration(View comboView,
View availableView)
{
using (ServerManager iisManager = new ServerManager())
{
int order = 1;
foreach (Site webSite in iisManager.Sites)
{
string id = webSite.Id.ToString(CultureInfo.InvariantCulture);
string name = webSite.Name;
string path = webSite.PhysicalPath();
StoreSiteDataInComboBoxTable(id, name, path, order , comboView);
StoreSiteDataInAvailableSitesTable(id, name, path, availableView);
}
}
}
private static void GetWebSitesViaMetabase(View comboView, View availableView)
{
using (DirectoryEntry iisRoot = new DirectoryEntry(IISEntry))
{
int order = 1;
foreach (DirectoryEntry webSite in iisRoot.Children)
{
if (webSite.SchemaClassName.ToLower(CultureInfo.InvariantCulture)
== IISWebServer)
{
string id = webSite.Name;
string name = webSite.Properties[ServerComment].Value.ToString();
string path = webSite.PhysicalPath();
StoreSiteDataInComboBoxTable(id, name, path, order , comboView);
StoreSiteDataInAvailableSitesTable(id, name, path, availableView);
}
}
}
}
private static void StoreSiteDataInComboBoxTable(string id, string name,
string physicalPath, int order, View comboView)
{
Record newComboRecord = new Record(5);
newComboRecord[1] = SessionEntry;
newComboRecord[2] = order;
newComboRecord[3] = id;
newComboRecord[4] = name;
newComboRecord[5] = physicalPath;
comboView.Modify(ViewModifyMode.InsertTemporary, newComboRecord);
}
private static void StoreSiteDataInAvailableSitesTable(string id, string name,
string physicalPath, View availableView)
{
Record newWebSiteRecord = new Record(3);
newWebSiteRecord[1] = id;
newWebSiteRecord[2] = name;
newWebSiteRecord[3] = physicalPath;
availableView.Modify(ViewModifyMode.InsertTemporary, newWebSiteRecord);
}
// determines if IIS7 upwards is installed so we know whether to use metabase
private static bool IsIIS7Upwards
{
get
{
bool isV7Plus;
using (RegistryKey iisKey = Registry.LocalMachine.OpenSubKey(IISRegKey))
{
isV7Plus = (int)iisKey.GetValue(MajorVersion) >= 7;
}
return isV7Plus;
}
}
#endregion
}
public static class ExtensionMethods
{
private const string IISEntry = "IIS://localhost/W3SVC/";
private const string Root = "/root";
private const string Path = "Path";
public static string PhysicalPath(this Site site)
{
if (site == null) { throw new ArgumentNullException("site"); }
var root = site.Applications.Where(a => a.Path == "/").Single();
var vRoot = root.VirtualDirectories.Where(v => v.Path == "/")
.Single();
// Can get environment variables, so need to expand them
return Environment.ExpandEnvironmentVariables(vRoot.PhysicalPath);
}
public static string PhysicalPath(this DirectoryEntry site)
{
if (site == null) { throw new ArgumentNullException("site"); }
string path;
using (DirectoryEntry de = new DirectoryEntry(IISEntry
site.Name Root))
{
path = de.Properties[Path].Value.ToString();
}
return path;
}
}
}
ПОЛЬЗОВАТЕЛЬСКИЙ интерфейс
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<CustomAction Id="UpdatePropsWithSelectedWebSite" BinaryKey="IISWebSiteCA"
DllEntry="UpdatePropsWithSelectedWebSite" Execute="immediate"
Return="check" />
<Binary Id="IISWebSiteCA" SourceFile="$(var.MyCA.TargetDir)MyCA.CA.dll" />
</Fragment>
<Fragment>
<UI>
<Dialog Id="InstallationAddress" Width="370" Height="270" Title="Experian">
<Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17"
Default="yes" Text="!(loc.WixUINext)">
<Condition Action="disable">WEBSITE = "" OR VD = ""</Condition>
<Condition Action="enable"><![CDATA[WEBSITE <> "" AND VD <> ""]]></Condition>
</Control>
<Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17"
Text="!(loc.WixUIBack)" />
<Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17"
Cancel="yes" Text="!(loc.WixUICancel)">
<Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
</Control>
<Control Id="Title" Type="Text" X="15" Y="6" Width="219" Height="15" Transparent="yes"
NoPrefix="yes" Text="!(loc.SelectInstallAddress)" />
<Control Id="Description" Type="Text" X="25" Y="23" Width="340" Height="15" Transparent="yes" NoPrefix="yes" Text="!(loc.SelectInstallationDescription)" />
<Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44"
TabSkip="no" Text="!(loc.InstallDirDlgBannerBitmap)" />
<Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
<Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
<Control Id="SelectWebSiteLabel" Type="Text" X="20" Y="105" Width="290" Height="10"
NoPrefix="yes" Text="!(loc.Site)" />
<Control Id="SelectWebSiteCombo" Type="ComboBox" X="20" Y="117" Width="250" Height="16"
Property="WEBSITE" Sorted="yes" ComboList="yes" />
<Control Type="Text" Id="VirtualDirectoryLabel" Width="290" Height="10" X="20" Y="140"
Text="!(loc.VirtualDirectory)" />
<Control Type="Edit" Id="VirtualDirectoryTextbox" Width="250" Height="18" X="20" Y="152"
Property="VD" />
<Control Type="Text" Id="InfoText1" Width="350" Height="17" X="10" Y="55"
Text="!(loc.Info1)" />
<Control Type="Text" Id="InfoText2" Width="350" Height="17" X="10" Y="75"
Text="!(loc.Info2)" />
</Dialog>
</UI>
</Fragment>
</Wix>
Ответ №1:
Две быстрые вещи:
- Я не вижу, где вы планируете свое действие здесь (только его определение и двоичную запись), поэтому я не уверен, что оно выполняется; записи в подробном журнале могут подтвердить или опровергнуть это. Даже если он запущен…
- Сеанс.Журнал не работает для действия, запущенного из диалогового окна (ограничения установщика Windows), поэтому, даже если оно запущено, оно не сообщит больше, чем о том, что действие было запущено. Один из распространенных обходных путей — убедиться, что вы регистрируете изменения свойств, и изменить свойство:
Session["LOGHACK"] = message;
Комментарии:
1. Прошу прощения, я не добавил основную информацию о продукте (бит, который управляет пользовательскими действиями). Я обновлю свой пост.