2

WixSharp (WiX へのマネージド コード インターフェイス) を使用して Web サイトをインストールし、AppPool を関連付ける方法の例を見つけようとしています。

私が達成したいステップは次のとおりです。

  1. Web サイトが IIS 6 に存在する場合は、削除します。
  2. IIS 6 に AppPool が存在する場合は、削除します。
  3. アプリケーション成果物を宛先ディレクトリーから削除します。
  4. 新しいアプリケーション アーティファクトを宛先ディレクトリにコピーします。
  5. AppPool を作成します。
  6. Web サイトを作成し、AppPool にリンクします。

私はこれを MSBuild で達成しましたが、MSI ほど有用ではありません。したがって、上記を WixSharp 構文で「書き直そう」としています。

WixSharp は明らかに WIXIISExtension をサポートしていますが、Google はまだ例を提供していません。

上記を WixSharp でどのようにコーディングしますか?

4

2 に答える 2

1

私は同じ目的でWIXを使用しています。デプロイしようとしているアプリケーションは約300MBであり、同じ仮想ディレクトリ、アプリプールなどを作成する必要があります。

あなたの要件は同じだと思います。

私はWIXがこれに本当に良いことを提案します。ユーザーの仮想ディレクトリ名、アプリケーションプールなどを尋ねる画面を表示できます。

WIXコードは、IIS 5.1、6、7で完全に機能します。7.5の場合、カスタムアクションを作成する必要があります。そのため、IIS 6互換モードがインストールされている場合は、wixを使用してIIS7.5でも仮想ディレクトリを作成できます。

これまで、WIXを使用してWebアプリケーションを展開する際にエラーが発生することはありませんでした。

于 2011-01-13T13:45:37.833 に答える
0

良い質問。

現在のプロジェクトで WixSharp を使用していますが、とても満足しています。すべてを C# 構文で行うことにより、XML ファイルの作成を回避できるのは素晴らしいことです。ところで、私はあなたが車輪の再発明をしているとは思いません... あなたは WixSharp で車輪をスピードアップしています.

WixSharp バージョン 1.9.6 では WebAppPool が関連付けられた Web サイトを作成できないため、CustomWebSite.cs ファイルを作成して作成しました。このようにして、次のコードを使用して Web アプリケーションを作成しました。

...

var project = new ManagedProject("My Project",
                       new InstallDir(@"c:\my_tool",

                            new Dir("my_frontend",
                                new Files($"{frontendDir}\\app\\*.*"),

                                    new CustomWebSite("GateKeeper", "*:31515")
                                    {
                                        WebApplication = new CustomWebApplication("DemoApp")
                                        {
                                            WebAppPool = new WebAppPool("DemoApp", "ManagedPipelineMode=Integrated;Identity=applicationPoolIdentity"),
                                        },
                                        InstallWebSite = true
                                    }
                                )
                            ),
...

これは、1 つの Web サイトを作成するためにのみ使用した CustomWebSite.cs ファイルです。

using System;
using System.Collections.Generic;
using System.Xml.Linq;
using WixSharp;
using WixSharp.CommonTasks;
using static WixSharp.WebSite;

namespace ToolBox.WixSharp
{
    /// <summary>
    /// Defines the WebSite element to be created associated to a Dir element.
    /// </summary>
    ///<example>The following is an example of associating a CustomWebSite to a Dir element.
    ///
    ///<code>
    /// var project =
    ///     new Project("My Product",
    ///         new Dir(@"%ProgramFiles%\My Company\My Product",
    ///             new Dir(@"some_dir",
    ///                 new CustomWebSite("MyApp", "*:81")
    ///                 {
    ///                     WebApplication = new CustomWebApplication("DemoApp")
    ///                     {
    ///                         WebAppPool = new WebAppPool("DemoApp", "ManagedPipelineMode=Integrated;Identity=applicationPoolIdentity")
    ///                     }
    ///                     InstallWebSite = true
    ///                 }
    ///         ...
    ///
    /// Compiler.BuildMsi(project);
    ///</code>
    /// 
    /// This code will generate something like this:
    ///<code>
    ///     <Component Id="DemoApp_WebSite" Guid="a6896bba-1818-43e0-824f-9c585b3e366b" KeyPath="yes" Win64="yes">
    ///         <iis:WebSite Id = "DemoApp_WebSite" Description="DemoApp_WebSite" Directory="INSTALLDIR.some_dir">
    ///             <iis:WebAddress Id = "WebSite_Address1" IP="*" Port="31515" />
    ///             <iis:WebApplication Id = "DemoApp_WebApplication" Name="DemoApp" WebAppPool="DemoApp_AppPool"/>
    ///         </iis:WebSite>
    ///         <iis:WebAppPool Id = "DemoApp_AppPool" Name="DemoApp" ManagedPipelineMode="Integrated" Identity="applicationPoolIdentity" />
    ///
    ///         <CreateFolder />
    ///         <RemoveFolder Id = "INSTALLDIR.some_dir" On="uninstall" />
    ///     </Component>
    /// </code>
    /// </example>
    public class CustomWebSite : WixEntity, IGenericEntity
    {
        /// <summary>
        /// Indicates if the WebSite is to be installed (created on IIS) or existing WebSite should be used to install the corresponding
        /// WebApplication. The default <see cref="InstallWebSite"/> value is <c>false</c>
        /// <para>Developers should be aware of the WebSite installation model imposed by WiX/MSI and use <see cref="InstallWebSite"/> carefully.</para>
        /// <para>If <see cref="InstallWebSite"/> value is set to <c>false</c> the parent WebApplication (<see cref="T:WixSharp.IISVirtualDir"/>)
        /// will be installed in the brand new (freshly created) WebSite or in the existing one if a site with the same address/port combination already exists
        /// on IIS). The undesirable side affect of this deployment scenario is that if the existing WebSite was used to install the WebApplication it will be
        /// deleted on IIS during uninstallation even if this WebSite has other WebApplications installed.</para>
        /// <para>The "safer" option is to set <see cref="InstallWebSite"/> value to <c>true</c> (default value). In this case the WebApplication will
        /// be installed in an existing WebSite with matching address/port. If the match is not found the installation will fail. During the uninstallation
        /// only installed WebApplication will be removed from IIS.</para>
        /// </summary>
        public bool InstallWebSite = false;

        /// <summary>
        /// Initializes a new instance of the <see cref="WebSite" /> class.
        /// </summary>
        public CustomWebSite()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CustomWebSite"/> class.
        /// </summary>
        /// <param name="description">The description of the web site (as it shows up in the IIS manager console).</param>
        /// <param name="addressDefinition">The address definition.</param>
        public CustomWebSite(string description, string addressDefinition)
        {
            this.Id = $"{description}_WebSite";
            this.Description = description;
            this.AddressesDefinition = addressDefinition;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CustomWebSite"/> class.
        /// </summary>
        /// <param name="id">The id</param>
        /// <param name="description">The description of the web site (as it shows up in the IIS manager console).</param>
        /// <param name="addressDefinition">The address definition.</param>
        public CustomWebSite(Id id, string description, string addressDefinition)
        {
            this.Id = id;
            this.Description = description;
            this.AddressesDefinition = addressDefinition;
        }

        internal void ProcessAddressesDefinition()
        {
            if (!AddressesDefinition.IsEmpty())
            {
                List<WebAddress> addressesToAdd = new List<WebAddress>();

                foreach (string addressDef in AddressesDefinition.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
                {
                    try
                    {
                        string[] tokens = addressDef.Split(":".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                        string address = tokens[0];
                        string port = tokens[1];
                        if (tokens[1].ContainsWixConstants())
                        {
                            addressesToAdd.Add(new WebAddress { Address = address, AttributesDefinition = "Port=" + port });
                        }
                        else
                        {
                            addressesToAdd.Add(new WebAddress { Address = address, Port = Convert.ToInt32(port) });
                        }
                    }
                    catch (Exception e)
                    {
                        throw new Exception("Invalid AddressesDefinition", e);
                    }
                }

                this.addresses = addressesToAdd.ToArray();
            }

        }

        /// <summary>
        /// References a WebAppPool instance to use as the application pool for this application in IIS 6 applications.
        /// </summary>
        public string WebAppPool; //WebApplication element attribute

        /// <summary>
        /// Specification for auto-generating the <see cref="T:WebSite.WebAddresses"/> collection.
        /// <para>If <see cref="AddressesDefinition"/> is specified, the existing content of <see cref="Addresses"/> will be ignored
        /// and replaced with the auto-generated one at compile time.</para>
        /// </summary>
        /// <example>
        /// <c>webSite.AddressesDefinition = "*:80;*90";</c> will be parsed and converted to an array of <see cref="T:WixSharp.WebSite.WebAddress"/> as follows:
        /// <code>
        /// ...
        /// webSite.Addresses = new []
        ///     {
        ///         new WebSite.WebAddress
        ///         {
        ///             Address = "*",
        ///             Port = 80
        ///         },
        ///         new WebSite.WebAddress
        ///         {
        ///             Address = "*",
        ///             Port = 80
        ///         }
        ///     }
        /// </code>
        /// </example>
        public string AddressesDefinition = "";

        //// The iis:WebSite/@Directory attribute must be specified when the element has a Component as an ancestor..
        //public string Directory = "";


        /// <summary>
        /// Reference to a WebApplication that is to be installed as part of this web site.
        /// </summary>
        public CustomWebApplication WebApplication = null;

        /// <summary>
        /// Collection of <see cref="T:WebSite.WebAddresses"/> associated with website.
        /// <para>
        /// The user specified values of <see cref="Addresses"/> will be ignored and replaced with the
        /// auto-generated addresses if <see cref="AddressesDefinition"/> is specified either directly or via appropriate <see cref="WebSite"/> constructor.
        /// </para>
        /// </summary>
        public WebAddress[] Addresses
        {
            get
            {
                ProcessAddressesDefinition();
                return addresses;
            }
            set
            {
                addresses = value;
            }
        }

        /// <summary>
        /// This class defines WebAppPool WiX element. It is used to specify the application pool for this application in IIS 6 applications.
        /// </summary>
        public partial class CustomWebApplication : WixEntity
        {
            /// <summary>
            /// References a WebAppPool instance to use as the application pool for this application in IIS 6 applications.
            /// </summary>
            public WebAppPool WebAppPool; //WebApplication element attribute

            /// <summary>
            /// Initializes a new instance of the <see cref="WebApplication"/> class.
            /// </summary>
            /// <param name="name">The name.</param>
            /// <param name="attributesDefinition">The attributes definition. This parameter is used to set encapsulated <see cref="T:WixSharp.WixEntity.AttributesDefinition"/>.</param>
            public CustomWebApplication(string name, string attributesDefinition)
            {
                base.Id = $"{name}_WebApplication";
                base.Name = name;
                base.AttributesDefinition = attributesDefinition;
            }

            /// <summary>
            /// Initializes a new instance of the <see cref="WebAppPool"/> class.
            /// </summary>
            /// <param name="name">The name.</param>
            public CustomWebApplication(string name)
            {
                base.Id = $"{name}_WebApplication";
                base.Name = name;
            }

            /// <summary>
            /// Initializes a new instance of the <see cref="WebAppPool"/> class.
            /// </summary>
            public CustomWebApplication()
            {
            }
        }

        WebAddress[] addresses = new WebAddress[0];

        /// <summary>
        /// Primary key used to identify this particular entry.
        /// </summary>
        [Xml]
        public new string Id
        {
            get
            {
                return base.Id;
            }
            set
            {
                base.Id = value;
            }
        }

        /// <summary>
        /// The value to set into the environment variable. If this attribute is not set, the environment variable is removed
        /// during installation if it exists on the machine.
        /// </summary>
        [Xml]
        public string Description;

        /// <summary>
        /// Defines the installation <see cref="Condition"/>, which is to be checked during the installation to
        /// determine if the registry value should be created on the target system.
        /// </summary>
        public Condition Condition;

        /// <summary>
        /// Adds itself as an XML content into the WiX source being generated from the <see cref="WixSharp.Project"/>.
        /// See 'Wix#/samples/Extensions' sample for the details on how to implement this interface correctly.
        /// </summary>
        /// <param name="context">The context.</param>
        public void Process(ProcessingContext context)
        {
            // IIS namespace
            XNamespace ns = WixExtension.IIs.ToXNamespace();

            XElement component = this.CreateAndInsertParentComponent(context);
            component.Add(this.ToXElement(ns + "WebSite"));

            XElement webSiteElement = component.FindAll("WebSite")[0];

            if (webSiteElement.Parent.Name == "Component" && webSiteElement.Parent.Parent.Name == "Directory")
            {
                // Add attributes for WebSite element
                webSiteElement.AddAttributes($"Directory={webSiteElement.Parent.Parent.Attribute("Id").Value}");
            }

            if (Addresses != null)
            {
                int index = 1;

                // Generates the XML fragment for WebAddress element
                foreach (WebAddress address in Addresses)
                {
                    webSiteElement.AddElement(new XElement(ns + "WebAddress",
                                            new XAttribute("Id", $"WebSite_Address{index}"),
                                            new XAttribute("IP", "*"),
                                            new XAttribute("Port", address.Port)));
                    index++;
                }
            }

            if (WebApplication != null)
            {
                // Generates the XML fragment for WebApplication element
                XElement webApplicationElement = new XElement(ns + "WebApplication",
                                        new XAttribute("Id", WebApplication.Id),
                                        new XAttribute("Name", this.WebApplication.Name));

                webSiteElement.AddElement(webApplicationElement);

                if (WebApplication.WebAppPool != null)
                {
                    WebApplication.WebAppPool.Id = $"{WebApplication.WebAppPool.Name}_WebAppPool";
                    webApplicationElement.SetAttribute($"WebAppPool={WebApplication.WebAppPool.Id}");

                    // Generates the XML fragment for WebAppPool element
                    webSiteElement.Parent.AddElement(new XElement(ns + "WebAppPool",
                                            new XAttribute("Id", WebApplication.WebAppPool.Id),
                                            new XAttribute("Name", WebApplication.WebAppPool.Name),
                                            new XAttribute("ManagedPipelineMode", "Integrated"),
                                            new XAttribute("Identity", "applicationPoolIdentity")));
                }
            }

            if (Condition != null)
            {
                component.AddElement(new XElement("Condition", Condition.ToXValue())
                         .AddAttributes(Condition.Attributes));
            }
        }
    }
}

また、 WebSite 定義に従って WIX xml ファイルを生成し、WixSourceGenerated イベントをサブスクライブできるXMLInjection を使用したWixSharp IIS サンプル に示されているように XML インジェクションを使用することによって、問題を解決する別の方法もあります 。

project.WixSourceGenerated += Compiler_WixSourceGenerated;

WixSharp は Wix XML 定義ファイルを生成し、WixSourceGenerated イベントの後にこの XML ファイルを変更できることに注意してください。

于 2019-04-13T00:07:38.987 に答える