IIS 安装的自定义操作 - ComboxBox 为空问题
我正在遵循许多不同的教程,试图制作一个通用的 IIS WIX 安装程序,然后我可以根据需要将其拆分到不同的库中。
教程
到目前为止,我已经有了一个在使用 /q 标志运行时似乎可以工作的安装。但是在交互模式下,应该填充组合框的自定义操作不起作用。
我尝试过调试,但遇到了以下问题:
- Session.Log 命令似乎没有在任何地方输出
- 附加到 msiexec 并调用 Debugger.Launch 或 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 = @"Software\Microsoft\InetStp";
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 result;
}
[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 result;
}
#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;
}
}
}
UI
<?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>
I'm following a number of different tutorials in an attempt to make a generic IIS WIX installer which I can then split up as appropriate into different libraries.
Tutorials
creating a web application installer with wix 3.5 and visual studio 2010 (Paul Reynolds blog)
Creating WIX Installer for ASP.NET Web Application (Code Project)
So far, I've got an installation that seems to work when run with the /q flag. However in interactive mode, the custom action which is supposed to populate the combo box isn't working.
I've tried to debug but I've come into the following problems:
- Session.Log commands don't seem to output anywhere
- Attaching to msiexec and calling Debugger.Launch or MmsiBreak seem to just exit straight away (even with breakpoints enabled).
Starting to get frustrating as it shouldn't be this difficult to take values from a custom action and pass them into a combo box.
Anybody have any ideas what could be the root cause, I'm expecting a lot of people have either used this code or something similar to it:
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 = @"Software\Microsoft\InetStp";
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 result;
}
[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 result;
}
#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;
}
}
}
UI
<?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>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
两件事:
Session["LOGHACK"] = message;
Two quick things:
Session["LOGHACK"] = message;