Select a Provisioning Option

by Tali Smith

Introduction

Both the IT administrator and the software developer need to consider the provisioning of Web sites in a hosting environment. The provisioning of Web sites in Internet Information Services (IIS) can be done in several ways:

  • Through the IIS Manager user interface (UI)
  • Programmatically, through use of C#
  • Through Windows PowerShell™ scripts

This article describes the advantages and disadvantages of the different options for IT administrators and software developers, and provides some examples. For more information, see Provisioning Options in IIS.

Use the UI or Remote Delegation

You can use IIS Manager, the management user interface that comes with IIS, to configure the most common properties in the ApplicationHost.config. Open the property sheets for a service, site, or virtual directory, and change values. Changes take place immediately without a need to stop and start the server.

  • Advantages
    When you create a site or virtual directory, or when you configure a feature with more than one property, the management user interface sets all the supporting properties. IIS Manager informs you if a new value is invalid.
  • Disadvantages
    Managing large IIS server configurations or multiple servers over the Internet can be slow and cumbersome. Not all configuration properties can be accessed in the user interface.

For instructions on using the UI to provision Web sites, see Create a Web Site (IIS 7).

Use the Text Editor

You can use a text editor such as Notepad to directly edit the ApplicationHost.config file while IIS is running. Entries are case sensitive.

  • Advantages
    You can change multiple properties or create new nodes in one instance without having to open and close multiple property sheets.
  • Disadvantages
    It is easy to corrupt an IIS server by using edit-while-running. If your edits include XML that is not formatted correctly, IIS cannot read the ApplicationHost.config and the last history file must be restored. If your edits include an invalid configuration that does not comply with the rules in the schema, an error is logged in the event viewer, but the rest of IIS can run.
    Property inheritance must be taken into consideration when cutting and pasting portions of the ApplicationHost.config. The section you paste might inherit properties from parent nodes and impart properties to child nodes.
    If you are using edit-while-running over the network and the connection fails, you might end up with an invalid ApplicationHost.config. Note that using edit-while-running on multiple servers in a Web farm takes as much time as using the user interface.

Use Windows Management Instrumentation (WMI)

You can use Windows® Management Instrumentation (WMI) to programmatically configure IIS in a script or compiled program. Changes take place immediately without needing to stop and start the server.

  • Advantages
    Configuring large sites or multiple servers with WMI is fast and efficient.WMI is also scriptable. An example of a WMI script follows.
  • Disadvantages
    If you create a site or virtual directory, or use a property that depends on others, you also must ensure that you know which supporting properties need to be created and set.

The following code can be used to create a Web site and an application pool.

If WScript.Arguments.Count < 4 Then 
    WScript.Echo "Not enough parameters. Enter: username | web site name | app pool password | site ID" 
    WScript.Quit
End If

userName = WScript.Arguments(0) 
siteName = WScript.Arguments(1)
appPoolPassword = WScript.Arguments(2)
siteID = WScript.Arguments(3) 
appPoolName = "apppool_" & siteName
physicalPath = "\\server\share" & userName & "\" & siteName [slg1] [slg2] 

Set oIIS = GetObject("winmgmts:root\WebAdministration")

Set oBinding = oIIS.Get("BindingElement").SpawnInstance_
oBinding.BindingInformation = "*:80:" & siteName
oBinding.Protocol = "http"

Set oBinding2 = oIIS.Get("BindingElement").SpawnInstance_
oBinding2.BindingInformation = "*:80:www." & siteName
oBinding2.Protocol = "http"
arrBindings = array(oBinding, oBinding2)

Set oSiteDefn = oIIS.Get("Site")
oSiteDefn.Create siteName, arrBindings, physicalPath
WScript.Echo "Site created"

WScript.Sleep(100)

Set oSite = oIIS.Get("Site.Name='" & siteName & "'")
oSite.ID = siteID 
oSite.Put_

Set oSite = oIIS.Get("Site.Name='" & siteName & "'")
appPoolUserName = "poolname_" & siteID

Set oAppDefn = oIIS.Get("ApplicationPool")
oAppDefn.Create appPoolName
WScript.Echo "App pool created"

WScript.Sleep(3000)

Set oAppDefn = oIIS.Get("ApplicationPool.Name='" & appPoolName & "'")
oAppDefn.ProcessModel.IdentityType = 3
oAppDefn.ProcessModel.Username = appPoolUserName
oAppDefn.ProcessModel.Password = appPoolPassword
oAppDefn.Put_ 

WScript.Echo "Identity set for App Pool"

Set oSiteDefn = oIIS.Get("Site.Name='" & siteName & "'")
oSiteDefn.ApplicationDefaults.ApplicationPool = appPoolName
oSiteDefn.Put_
WScript.Echo "Site assigned to pool"

Set oSite = oIIS.Get("Site.Name='" & siteName & "'")
oSite.Start

Use AppCmd.exe

AppCmd.exe can be used to provision Web sites and run many commands to edit configuration.

The following code sample is an example of code that can be used to create a site and an application pool (with failed request tracing and W3svc log file locations).

%windir%\system32\inetsrv\Appcmd add AppPool -name:%poolname% -processModel.username:%poolaccount% -processModel.password:%poolaccountpwd% -enable32BitAppOnWin64:true

%windir%\system32\inetsrv\AppCmd add site -name:%sitename% -bindings:http/*:80:%sitename% -physicalPath:%sitepath% -logfile.directory:%W3svclogpath% -traceFailedRequestsLogging.directory:%FREBlogpath%

%windir%\system32\inetsrv\Appcmd set app -app.name:%sitename%/ -applicationPool:%poolname%

You can use the following code to configure the Failed Request Tracing log file location:

%windir%\system32\inetsrv\AppCmd set config <sitename> -section:traceFailedRequestsLogging.directory:\\remoteserver\content$\<sitename>\logs\failedReqLog

You can use the following code to configure the W3SVC log file location:

%windir%\system32\inetsrv\AppCmd set config <sitename> -section:-logfile.directory:\\remotefileshare\content$\<sitename>\logs\logfiles

Use a Managed API (Microsoft.Web.Administration)

You can use managed application programming interfaces (APIs) in Microsoft.Web.Administration to programmatically configure IIS in any Microsoft® .NET application. Microsoft.Web.Administration is a new API in IIS that allows developers using managed code to read and manipulate the server configuration in a simple way.

  • Advantages
    Configuring large sites or multiple servers is fast and efficient with Microsoft.Web.Administration. Microsoft.Web.Administration can be managed using remote procedure call (RPC) for remote server configuration. Microsoft.Web.Administration can create as many as 100,000 sites within 62 seconds (approximately 1,600 sites/sec).
  • Disadvantages
    Microsoft.Web.Administration can only be used on the Windows® operating system. Many objects are not exposed as strongly-typed objects, therefore, you must understand the lower level APIs to configure certain objects and properties.

The following code can be used to create a site and an application pool and to set temporary compilation directories.

using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using Microsoft.Web.Administration;

namespace IIS7Demos
{
   class CreateSites
   {
      const int NUMBEROFSITES = 100;
      const int SITEBASENUMBER = 1000;
      const string POOLPREFIX = "POOL_";
      const string SITENAMEPREFIX = "SITE";
      const string ROOTDIR = "e:\\content"; 

   static void Main(string[] args)
   { 
      ServerManager mgr = new ServerManager();
      SiteCollection sites = mgr.Sites;

      Stopwatch watch = new Stopwatch();
      watch.Start();

      for (int i = SITEBASENUMBER; i < NUMBEROFSITES+SITEBASENUMBER; i++)
      {
         if (!CreateSitesInIIS(sites, SITENAMEPREFIX, i, ROOTDIR))
         {
            Console.WriteLine("Creating site {0} failed", i);
         }

         if (!CreateAppPoolInIIS(mgr, SITENAMEPREFIX, i))
         {
            Console.WriteLine("Creating apppool {0} failed", i);
         }
      }

      mgr.CommitChanges();
      watch.Stop();
      Console.WriteLine("Creating {0} sites took {1} seconds", NUMBEROFSITES, ((double)watch.ElapsedMilliseconds) / 1000f);
   }

   static bool CreateSitesInIIS(SiteCollection sites, string sitePrefix, int siteId, string dirRoot)
   {
      string siteName = sitePrefix + siteId;
      // site gets set to Poolname using the following format. Example: 'Site_POOL10'
      string poolName = POOLPREFIX + sitePrefix + siteId;

      try
      {
         Site site = sites.CreateElement();
         site.Id = siteId;
         site.SetAttributeValue("name", siteName);
         sites.Add(site);

         Application app = site.Applications.CreateElement();
         app.SetAttributeValue("path", "/");
         app.SetAttributeValue("applicationPool", poolName);
         site.Applications.Add(app);

         VirtualDirectory vdir = app.VirtualDirectories.CreateElement();
         vdir.SetAttributeValue("path", "/");
         vdir.SetAttributeValue("physicalPath", dirRoot + @"\" + siteName);

         app.VirtualDirectories.Add(vdir);

         Binding b = site.Bindings.CreateElement();
         b.SetAttributeValue("protocol", "http");
         b.SetAttributeValue("bindingInformation", ":80:" + siteName);
         site.Bindings.Add(b);
      }
      catch (Exception ex)
      {
         Console.WriteLine("Create site {0} failed. Reason: {1}", siteName, ex.Message);
         return false;
      }
      return true;
   }

   static bool CreateAppPoolInIIS(ServerManager mgr, string sitePrefix, int siteId)
   {
      string poolName = POOLPREFIX + sitePrefix + siteId;

      try
      {
         mgr.ApplicationPools.Add(poolName);
         ApplicationPool apppool = mgr.ApplicationPools[poolName];
         apppool.ManagedPipelineMode = ManagedPipelineMode.Integrated;
      }

      catch (Exception ex)
      {
         Console.WriteLine("Create site {0} failed. Reason: {1}", poolName, ex.Message);
         return false;
      }
      return true;
   }
  }
}

To set a unique temporary compilation directory for each site, use the following code:

using System;
using Microsoft.Web.Administration;
public class setASPNETCompilationDirectory
{
   static void Main()
   {
      ServerManager manager = new ServerManager();
      Configuration rootConfig = manager.GetWebConfiguration(new WebConfigurationMap(), null);
      ConfigurationSection section = rootConfig.GetSection("system.web/compilation");
      section.Attributes["tempDirectory"].Value = @"e:\inetpub\temp\temporary asp.net files\site1";
      section.SetMetadata("lockAttributes", "tempDirectory");
      manager.CommitChanges();
   }
}

Use Active Directory Service Interfaces (ADSI)

You can use the Active Directory® Service Interfaces (ADSI) to programmatically configure IIS in a script or compiled program. Changes take place immediately without a need to stop and start the server.

  • Advantages
    Configuring large sites or multiple servers with ADSI is fast and efficient. ADSI is scriptable, and you can configure IIS 4.0, IIS 5.0, IIS 5.1, and IIS 6.0, and IIS7 and above (with IIS6 compatible-mode enabled) with ADSI, as long as you use error checking to handle missing objects and properties. You can also extend the IIS schema with ADSI, though it is not recommended.
  • Disadvantages
    If you create a site or virtual directory, or use a property that depends on others, you also must ensure that you know which supporting properties need to be created and set. ADSI is only available for IIS 7 and above if IIS 6 compatible mode is enabled. Note that it is also difficult to use.

Use OLE Automation

OLE Automation (ProgId=Microsoft.ApplicationHost.WritableAdminManager) can be used from Microsoft® JScript® and Microsoft® Visual Basic® Scripting Edition (VBScript).

  • Advantages
    Configuring large sites or multiple servers is fast and efficient. OLE automation is actually slightly faster than Microsoft.Web.Administration, and it is also remoteable.
  • Disadvantages
    You need to have an understanding of the lower level APIs to configure certain objects and properties. It requires RPC for remote server configuration.

Use Admin Base Objects (ABO)

Use ABO to programmatically configure IIS in a compiled program written in C, C++, or Microsoft® Visual Basic® 6.0.

  • Advantages
    It is faster than using ADSI or WMI because the ADSI and WMI providers are wrappers for ABO.
  • Disadvantages
    If you create a site or virtual directory, or use a property that depends on others, you also must ensure that you know which supporting properties need to be created and set.
    ABO is not scriptable. ABO applications can only be written in C++ or Visual Basic 6.0.
    Since ABO accesses IIS at the lowest level, it is more difficult to use than ADSI or WMI because there are no methods that compress multiple lines of ABO code into one method call. Also, there are no safeguards to prevent you from configuring invalid settings.

Note

This article updates the articles in: "Code Samples and Scripts" by Walter Oliver, published on December 2, 2007.