Posted by: John Barshinger | October 27, 2006

How to modify the VS2005 Installer to set the ASP.NET version and create Application Pools

 
In my previous blog entry, I complained about no satisfactory installer out there I could buy that meets my requirements for installing an ASP.NET application. In this entry, I will discuss the solution I came up with to use the built-in VS2005 installer to automatically set the ASP.NET version for the application being installed and to create an Application Pool to use for that application if being installed on Windows 2003/IIS6.
 
Basically, what you need to do is create a custom installer class and call this class from the "install" action of your Custom Actions view on your Web Application installer project. You also need to pass some parameters from the installer to your custom installer class. All this is well documented in MSDN or other web sites you can google so I won’t waste time with that here. Instead, I’ll just show the code to do all the work. Pieces of this are available by searching the internet as well but this shows the whole thing together from a code perspective.
 
You can pass data to your customer installer class via the "CustomActionData" attribute in the properties for the custom action. In our case, we set this attribute as follows:
 
/iisv="[IISVERSION]" /tv="[TARGETVDIR]" /ts="[TARGETSITE]"
 
Here’s the code (updated 11/13/2006):
 
using System;
using System.Collections;
using System.ComponentModel;
using System.Configuration.Install;
using System.Diagnostics;
using System.DirectoryServices;
using System.IO;
namespace InstallerCustomAction
{
    [RunInstaller(true)]
    public partial class SetASPNetVersionAndCreateAppPool : Installer
    {
        public const bool debug = false;
        public const string MetaBasePathToAppPools = "IIS://localhost/W3SVC/AppPools";
        public const string IIS6 = "#6";
        public const string TargetASPNETVersion = "v2.0.50727";
        public const string TargetSiteTag = "ts";
        public const string TargetVDirTag = "tv";
        public const string IISVersionTag = "iisv";
        public const string SSSolutionsAppPoolName = "SS Solutions " + TargetASPNETVersion;
        protected StreamWriter logFile = null;
        public SetASPNetVersionAndCreateAppPool()
        {
            InitializeComponent();
        }
       
        public override void Install(IDictionary stateSaver)
        {
            base.Install(stateSaver);
            if (debug)
            {
                logFile = File.CreateText(@"C:\SANVACAP.txt");
                WriteToLogFile("IISVersion: " + Context.Parameters[IISVersionTag]);
                WriteToLogFile("TargetVDir: " + Context.Parameters[TargetVDirTag]);
                WriteToLogFile("TargetSite: " + Context.Parameters[TargetSiteTag]);
            }
            // the following parameters must be passed in via the CustomActionData property of the CustomAction for the Install Method
            // /iisv=[IISVERSION] /tv=[TARGETVDIR] /ts=[TARGETSITE]
            if ((!string.IsNullOrEmpty(Context.Parameters[TargetSiteTag])) && (!string.IsNullOrEmpty(Context.Parameters[TargetVDirTag])))
            {
                string targetVDir = Context.Parameters[TargetVDirTag];
                string targetSite = Context.Parameters[TargetSiteTag];
                if (targetSite.StartsWith("/LM/"))
                {
                    targetSite = targetSite.Substring(4);
                }
                // if we’re installing on IIS6, create an Application Pool and put the assign the vDir to that pool
                string IISVersion = Context.Parameters[IISVersionTag];
                if ((!string.IsNullOrEmpty(IISVersion)) && (IISVersion.Equals(IIS6)))
                {
                    CreateWebApplicationAndAppPool(targetSite, targetVDir, SSSolutionsAppPoolName);
                }
 
                // assign the asp net version to the vDir
                SetWebApplicationASPNetVersion(targetSite, targetVDir, TargetASPNETVersion);
            }
            if (debug) logFile.Close();
        }
        #region Utility Methods
        /// <summary>
        /// CreateWebApplicationAndAppPool("W3SVC/2", "UniversitySite", "MyAppPool");
        /// </summary>
        /// <param name="targetSite">metabase path to the website to use</param>
        /// <param name="targetVDir">virtual directory version</param>
        /// <param name="appPoolName">appPoolName is of the form "<name>", for example, "MyAppPool"</param>
        protected void CreateWebApplicationAndAppPool(string targetSite, string targetVDir, string appPoolName)
        {
            string metabasePath = String.Format("IIS://localhost/{0}/Root/{1}", targetSite, targetVDir);
            WriteToLogFile(String.Format("Assigning application {0} to the application pool named {1}:", metabasePath, appPoolName));
            try
            {
                DirectoryEntry vDir = new DirectoryEntry(metabasePath);
                string className = vDir.SchemaClassName.ToString();
                if ((className.EndsWith("VirtualDir")) || (className.EndsWith("WebDirectory")))
                {
                    // put the vdir in the desired app pool, creating the app pool if necessary
                    object[] param = { 2, appPoolName, true };
                    vDir.Invoke("AppCreate3", param);
 
                    // assign the application friendly name
                    vDir.Properties["AppFriendlyName"][0] = targetVDir;
                    // save the changes
                    vDir.CommitChanges();
                   
                    WriteToLogFile(" Done: classname=" + className);
                }
                else
                {
                    WriteToLogFile(" Failed in AssignVDirToAppPool; only virtual directories can be assigned to application pools: classname=" + className);
                }
            }
            catch (Exception ex)
            {
                WriteToLogFile(String.Format("Failed in AssignVDirToAppPool with the following exception: {0}", ex.Message));
            }
        }
       
        /// <summary>
        /// SetWebApplicationASPNetVersion("W3SVC/2", "UniversitySite", "v2.0.50727");
        /// </summary>
        /// <param name="targetSite">metabase path to the website to use</param>
        /// <param name="targetVDir">virtual directory version</param>
        /// <param name="ASPNetVersion">asp net version number as specified in the path to the directory in the file system</param>
        protected void SetWebApplicationASPNetVersion(string targetSite, string targetVDir, string ASPNetVersion)
        {
            WriteToLogFile(String.Format("Assigning ASPNetVersion {0} to the vDir named {1} on WebSite {2}:", ASPNetVersion, targetVDir, targetSite));
            try
            {
                ProcessStartInfo processStartInfo = new ProcessStartInfo();
                processStartInfo.FileName = Path.Combine(Environment.GetEnvironmentVariable("SystemRoot"),
                                                         @"Microsoft.NET\Framework\" + ASPNetVersion + @"\aspnet_regiis.exe");
                processStartInfo.Arguments = string.Format("-s {0}/Root/{1}", targetSite, targetVDir);
                processStartInfo.CreateNoWindow = true;
                processStartInfo.UseShellExecute = false;
                Process.Start(processStartInfo);
                WriteToLogFile(" Done executing: " + processStartInfo.FileName + " " + processStartInfo.Arguments);
            }
            catch (Exception ex)
            {
                WriteToLogFile(String.Format("Failed in AssignASPNetVersionToVDir with the following exception: {0}", ex.Message));
            }
        }
 
        protected void WriteToLogFile(string Message)
        {
            if (debug) logFile.WriteLine(Message);
        }
        #endregion
    }
}

Leave a comment

Categories