【问题标题】:In WiX how can I select an IIS website by name?在 WiX 中,如何按名称选择 IIS 网站?
【发布时间】:2010-11-23 17:29:13
【问题描述】:

我想做的是向安装程序用户显示他们服务器上的网站列表,并允许他们选择一个(使用此处描述的方法:http://www.cmcrossroads.com/content/view/13160/120/,现在似乎已损坏,请参阅here 获取核心代码)。然后安装程序将在所选网站中创建一个虚拟目录。

但是,我的搜索似乎表明,在 WiX 中指定网站的唯一方法是通过 IP、端口和标头。要求这些对用户来说不是很友好,所以我想编写第二个自定义操作来从网站名称中获取这些详细信息。

有没有更好的办法?

顺便说一句,这需要在 IIS6 和 IIS7 中工作,以防影响答案。

【问题讨论】:

    标签: iis iis-7 iis-6 wix wix3


    【解决方案1】:

    根据 Cheeso 的回答和更新的自定义操作,将 C# 与 Microsoft.Web.Administration 结合使用,而不是 Javascript 与 WMI 结合使用。针对 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;
        }
    }
    

    像这样注册自定义操作:

        <Binary Id='WiXCustomActionsDLL' SourceFile='CustomActions.CA.dll' />
    
    
        <CustomAction Id="GetWebsitesAction"
                      Return="check"
                      Execute="immediate"
                      BinaryKey="WiXCustomActionsDLL"
                      DllEntry="GetWebsites" />
    
        <InstallUISequence>
          <Custom Action='GetWebsitesAction' Before='AppSearch' />
        </InstallUISequence>
    
        <!-- Updating IISROOT in the UI does not update the value of it's sub-directory INSTALLLOCATION.
             So we have this to force the update of INSTALLLOCATION with a custom action. -->
        <CustomAction Id="ChangeDir" Directory="INSTALLLOCATION" Value="[IISROOT]ProjectWebSite" />
        <InstallExecuteSequence>
          <Custom Action='ChangeDir' After='CostFinalize'></Custom>
        </InstallExecuteSequence>
    
    
    
        <!-- This populates properties for IISROOT and WEBSITE_PORT after this before files are installed -->
        <CustomAction Id="UpdatePropsWithSelectedWebSiteAction"
                      Return="check"
                      Execute="immediate"
                      BinaryKey="WiXCustomActionsDLL"
                      DllEntry="UpdatePropsWithSelectedWebSite" />
    

    对话框 wxs 如下所示:

    <UI>
    
      <Dialog Id="IISDlg" Width="370" Height="270" Title="[ProductName] Setup" NoMinimize="yes">
    
        <Control Id="SelectWebSiteLabel" Type="Text" X="20" Y="73" Width="100" Height="15" NoPrefix="yes" Text="Select web site:" />
        <Control Id="SelectWebSiteCombo" Type="ListBox" X="20" Y="89" Width="200" Height="150" Property="WEBSITE" Sorted="yes" />
    
        <Control Id="VirtualHostLabel" Type="Text" X="235" Y="73" Width="100" Height="15" TabSkip="no" Text="&amp;Application Path Alias:" />
        <Control Id="VirtualHostTextbox" Type="Edit" X="235" Y="89"  Height="17" Width="120" Property="IIS_VIRTUAL_DIR" Indirect="no" />
    
    
        <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="&amp;Back">
          <Publish Event="NewDialog" Value="MaintenanceTypeDlg" Order="1">Installed</Publish>
          <Publish Event="NewDialog" Value="LicenseAgreementDlg" Order="2">NOT Installed</Publish>
        </Control>
        <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="&amp;Next">
          <Publish Event="NewDialog" Value="CMParametersDlg">1</Publish>
          <Publish Event="DoAction" Value="UpdatePropsWithSelectedWebSiteAction">1</Publish>
        </Control>
        <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="Cancel">
          <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
        </Control>
        <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="WixUI_Bmp_Banner" />
        <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>Configure settings for your Web Server</Text>
        </Control>
        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
        <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>{\WixUI_Font_Title}Settings</Text>
        </Control>
        <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
      </Dialog>
    </UI>
    

    注意 Next 按钮控件中的 DoAction 事件。这将运行自定义操作以使用所选网站更新属性。

    然后按照 Dan 关于在应用更改时使用 SiteId="*' 的回答。

    【讨论】:

      【解决方案2】:

      回复IisEnumSites:Exception: 0x80004005 : Modify, Mode, Record

      我有类似的经历,到目前为止我发现的是从parseInt中提取的站点ID:

      record = Session.Installer.CreateRecord(6);
      record.IntegerData(1) = parseInt(site.Name.substr(6));  // WebSiteNo
      

      我有一个名称类似于W3SVC/1528550093 的网站,我怀疑1528550093 对于AvailableWebSites 表来说太大了。

      一旦我有 if 语句来过滤掉这些大数字,脚本就可以正常工作了。

      希望对其他人有所帮助。

      【讨论】:

        【解决方案3】:

        在我的安装程序中,我不想创建一个网站。我想让用户选择一个现有的网站。我使用 Javascript 中的自定义操作和一个自定义 UI 面板来做到这一点。


        自定义操作代码:

        //
        // CustomActions.js 
        // 
        // Custom Actions usable within WIX For IIS installations.
        // 
        // EnumerateWebSites_CA(): 
        //   Adds new UI to the MSI at runtime to allow the user to select a
        //   website, to which an ISAPI filter will be added.
        // 
        // UpdatePropsWithSelectedWebSite_CA():
        //   fills session with properties for the selected website. 
        //
        // SetAuthProps_CA():
        //   sets properties for the needed user and group that needs authorization to the created dir. 
        //
        // 
        // original idea from: 
        // http://blog.torresdal.net/2008/10/24/WiXAndDTFUsingACustomActionToListAvailableWebSitesOnIIS.aspx
        // 
        // Mon, 23 Nov 2009  10:54
        //
        // 
        // ===================================================================
        
        // http://msdn.microsoft.com/en-us/library/aa372516(VS.85).aspx
        
        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.
            };
        
        //*****************************************************************************
        // Purpose: Custom action that enumerates the local websites, and stores their
        // properties in the ListBox and AvailableWebSites tables.
        // Effects: Fills the ListBox table and creates and fills the AvailableWebSites
        // tables.
        // Returns: MsiActionStatus.Ok  if the custom action executes without error.
        //          MsiActionStatus.Abort if error. 
        //*****************************************************************************
        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 bby 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.
                //  old quote:  `````` 
                //  my quote:  '''''
        
        //        var createCmd = Session.Database.OpenView("CREATE TABLE 'AvailableWebSites' ('WebSiteNo' INT NOT NULL, 'WebSiteDescription' CHAR(50), 'WebSitePort' CHAR(50) NOT NULL, 'WebSiteIP' CHAR(50), 'WebSiteHeader' CHAR(50) PRIMARY KEY 'WebSiteNo')")
        
                var createCmd = Session.Database.OpenView("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)")
                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");
        
                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. 
                var 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;
        }
        
        
        
        //*****************************************************************************
        // Purpose: Custom action that copies the selected website's properties from the
        // AvailableWebSites table to properties.
        // Effects: Fills the WEBSITE_DESCRIPTION, WEBSITE_PORT, WEBSITE_IP, WEBSITE_HEADER
        // properties.
        // Returns: MsiActionStatus.Ok  if the custom action executes without error.
        //          MsiActionStatus.Abort if error. 
        //*****************************************************************************
        function UpdatePropsWithSelectedWebSite_CA()
        {
            try 
            {
                LogMessage("function UpdatePropsWithSelectedWebSite_CA() ENTER");
                var selectedWebSiteId = Session.Property("WEBSITE");
        
                LogMessage("selectedWebSiteId(" + selectedWebSiteId + ") type(" + typeof selectedWebSiteId + ")");
        
                // check if the user selected anything
                if (selectedWebSiteId == "")
                {
                    LogMessage("function UpdatePropsWithSelectedWebSite_CA() EXIT (None)");
                    return MsiActionStatus.None;
                }
        
                if (selectedWebSiteId.toUpperCase() == "SERVER")
                {
                    Session.Property("WEBSITE_NAME")        = "W3SVC";
                    Session.Property("WEBSITE_DESCRIPTION") = "Server";
                    Session.Property("WEBSITE_PORT")        = "";
                    Session.Property("WEBSITE_IP")          = "";
                    Session.Property("WEBSITE_HEADER")      = "";
                    LogMessage("function UpdatePropsWithSelectedWebSite_CA() EXIT (Ok)");
                    return MsiActionStatus.Ok;
                }
        
                var websitesView = Session.Database.OpenView("SELECT * FROM `AvailableWebSites` WHERE `Num`=" + selectedWebSiteId);
                websitesView.Execute();
                var record = websitesView.Fetch();
        
                LogMessage("website Fetch() complete");
        
                if (record.IntegerData(1) == parseInt(selectedWebSiteId))
                {
                    Session.Property("WEBSITE_NAME")        = record.StringData(2);
                    Session.Property("WEBSITE_DESCRIPTION") = record.StringData(3);
                    Session.Property("WEBSITE_PORT")        = record.StringData(4);
                    Session.Property("WEBSITE_IP")          = record.StringData(5);
                    Session.Property("WEBSITE_HOSTNAME")    = record.StringData(6);
                }
                websitesView.Close();
        
                LogMessage("function UpdatePropsWithSelectedWebSite_CA() EXIT (Ok)");
            }
        
            catch (exc1)
            {
                Session.Property("CA_EXCEPTION") = exc1.message ;
                LogException(exc1);
                return MsiActionStatus.Abort;
            }
            return MsiActionStatus.Ok;
        }
        
        
        // 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) = "IisEnumSites: Exception: 0x" + decimalToHexString(exc.number) + " : " + exc.message;
            Session.Message(MsgKind.Error + Icons.Critical + Buttons.btnOkOnly, record);
        }
        
        
        // spool an informational message into the MSI log, if it is enabled. 
        function LogMessage(msg)
        {
            var record = Session.Installer.CreateRecord(0);
            record.StringData(0) = "IisEnumSites: " + msg;
            Session.Message(MsgKind.Log, record);
        }
        
        
        
        function decimalToHexString(number)
        {
            if (number < 0)
            {
                number = 0xFFFFFFFF + number + 1;
            }    
            return number.toString(16).toUpperCase();
        }
        
        
        // Testing only
        function Test1_CA()
        {
            var record = Session.Installer.CreateRecord(0);
            record.StringData(0) = "Hello, this is an error message";
            Session.Message(msgKindUser + iconInformation + btnOk, record);
            return MsiActionStatus.Ok;
        }
        

        像这样注册自定义操作:

        <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
        
          <Fragment>
            <Binary Id="IisScript_CA" SourceFile="CustomActions.js" />
        
            <CustomAction Id="EnumerateWebSites"
                          BinaryKey="IisScript_CA"
                          JScriptCall="EnumerateWebSites_CA"
                          Execute="immediate"
                          Return="check" />
        
            <CustomAction Id="UpdatePropsWithSelectedWebSite"
                          BinaryKey="IisScript_CA"
                          JScriptCall="UpdatePropsWithSelectedWebSite_CA"
                          Execute="immediate"
                          Return="check" />
        
          </Fragment>
        
        </Wix>
        

        这是 UI 面板的 .wxs:

        <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
        
          <Fragment>
            <UI>
              <Dialog Id="SelectWebSiteDlg" Width="370" Height="270" Title="Select a Web Site">
                <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="Next" />
                <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="Back" />
                <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="Cancel">
                  <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
                </Control>
                <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes" Text="Please select which web site you want to install to." />
                <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes" Text="Select a Web Site" />
                <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="60" Width="290" Height="14" NoPrefix="yes" Text="Select the web site for the filter:" />
                <Control Id="SelectWebSiteCombo" Type="ListBox" X="20" Y="75" Width="200" Height="150" Property="WEBSITE" Sorted="yes" />
              </Dialog>
            </UI>
          </Fragment>
        </Wix>
        

        UI 面板显示一个列表框,该列表框自动填充 ListBox 表中的元素,其中第一个字段为 WEBSITE。此表在运行时由 Javascript 中的自定义操作填充。

        要在正确的时间调用自定义操作,您需要在主 .wxs 文件中添加如下内容:

        <InstallUISequence>
          <Custom Action="EnumerateWebSites" After="CostFinalize" Overridable="yes">NOT Installed</Custom>
        </InstallUISequence>
        

        【讨论】:

        • 知道为什么上面的脚本会抛出“IisEnumSites:Exception: 0x80004005 : Modify, Mode, Record”错误消息吗?
        • 啊,不,我不知道。
        【解决方案4】:

        虽然这个问题和答案仍然有效,但我认为值得问问自己是否真的要使用网站名称。如果您想存储它以在卸载期间使用,那么保存站点 ID 可能是一个更好的主意。在这种情况下,网站元素变为:

        <iis:WebSite Id="IisWebsite" Description="Dummy" SiteId="[IIS_WEBSITEID]">
          <iis:WebAddress Id="IisWebAddress" Port="80" />
        </iis:WebSite>
        

        【讨论】:

          【解决方案5】:

          好的,这是可能的(在具有 Metabase 兼容性的 IIS6 或 IIS7 中),感谢this 在邮件列表中发布,解释了 iis:Website 元素的工作方式有点奇怪。有用的部分是:

          Using a fragment like this and test with v3.0.5120.0:*
          
            <iis:WebSite Id="WebSite" Description="Default Web Site" SiteId="*">
              <iis:WebAddress Id="TestWebSite" Port="1" />
            </iis:WebSite>
          
          The following work:
          
          1. If WebSite/@SiteId="*" then a case sensitive match on WebSite/@Description happens.
          2. If WebSite/@SiteId matches the site id than WebSite/@Description is ignored and a match on site id happens.
          3. If WebSite/@SiteId has any value WebAddress/@Port is ignored (although the syntax requires it and it can't be 0).
          4. If WebSite/@SiteId is missing WebAddress/@Port is used and WebSite/@Description is ignored.
          5. Once a website is created and gets site id, you can rename it (therefore its site id is not the hash of its name), the WebSite/@SiteId="*" syntax will match on the WebSite/@Description.
          

          所以我的 WiX 代码最终看起来像:

          <DirectoryRef Id="TARGETDIR">
            <Component Id="IisSetup" Guid="YOUR-GUID-HERE">
              <iis:WebVirtualDir Id="IisVirtualDir" Alias="[IIS_VIRTUALDIRNAME]" Directory="INSTALLLOCATION" WebSite="IisWebsite">
                <iis:WebApplication Id="IisWebApplication" Name="[IIS_VIRTUALDIRNAME]" WebAppPool="IisAppPool" Isolation="high"/>
              </iis:WebVirtualDir>
              <iis:WebAppPool Id="IisAppPool" Name="[IIS_APPPOOLNAME]" Identity="networkService"/>
            </Component>
          </DirectoryRef>
          
          <!-- Note that this entry should not be put under a component. If it is WiX
               will update the website on install and remove it on uninstall -->
          <iis:WebSite Id="IisWebsite" Description="[IIS_WEBSITENAME]" SiteId="*">
            <iis:WebAddress Id="IisWebAddress" Port="80" />
          </iis:WebSite>
          

          iis:WebAddress 元素不应被使用,但它是项目编译所必需的。

          【讨论】:

            猜你喜欢
            • 2010-09-29
            • 2010-12-11
            • 2021-07-19
            • 2011-11-27
            • 1970-01-01
            • 1970-01-01
            • 2014-07-30
            • 2015-07-14
            • 2020-05-17
            相关资源
            最近更新 更多