Provisioning IIS-artifacts within an SSIS-package as part of a deployment process with C#

SSIS is not only suitable as “etl-processing-tool”. Its feature-set makes it a really good candidate for deployment processes, too.

In this multi-tenant scenario SSIS is used to provision a complete client-environment which also includes an application portal per tenant.
This portal is created using the following simplified script task inside SSIS.

Add a reference to Microsoft.Web.Administration which resides somewhere in your windows-folder. In my case its C:\Windows\SysWOW64\inetsrv\Microsoft.Web.Administration.dll.

using Microsoft.Web.Administration;

Add a script-task to your SSIS-package and create the privisioning logic …

public void Main()
{
  // These parameters are passed in from SSIS
  string clientAppCode = (string)Dts.Variables["Tenant::CustomShortCode"].Value;
  string svcUser = (string)Dts.Variables["Tenant::WinAccountUserFull"].Value;
  string svcPswd = (string)Dts.Variables["Tenant::WinAccountPassword"].Value;
  string webRoot = (string)Dts.Variables["Tenant::IISRootDir"].Value;
 
  // Build the app-name
  string appName = String.Format("{0}.customsoft.de", clientAppCode);
 
  // Process IIS articfacts
  using (ServerManager serverManager = new ServerManager())
  {
    if (serverManager.ApplicationPools[appName] != null)
    {
      // App pool already exists! Proceed with your error-handling ...
      Dts.TaskResult = (int)ScriptResults.Failure;
      return;
    }
 
    // Create a new application pool running .Net 4.* with the given user-identity
    ApplicationPool newPool = serverManager.ApplicationPools.Add(appName);
    newPool.ManagedRuntimeVersion = "v4.0";
    newPool.ProcessModel.UserName = svcUser;
    newPool.ProcessModel.Password = svcPswd;
    newPool.ProcessModel.IdentityType = ProcessModelIdentityType.SpecificUser;
 
    // Provision the app-pool
    serverManager.CommitChanges();
 
    // Create the (web-)site
    if (serverManager.Sites[appName] != null)
    {
      // Site already exists! Proceed with your error-handling ...
      Dts.TaskResult = (int)ScriptResults.Failure;
      return;
    }
 
    // Create the website with the specified bindings. Of course here is 443/SSL missing ;-)
    Site clientSite = serverManager.Sites.Add(appName, "http", String.Format("*:80:{0}.customsoft.de", clientAppCode), webRoot);
 
    // Add another binding for www.clientcode.customsoft.de
    clientSite.Bindings.Add("*:80:www." + clientAppCode + ".customsoft.de", "http"); 
 
    // Assign the newly created app-pool to the new site
    site.ApplicationDefaults.ApplicationPoolName = newPool.Name;
 
    serverManager.CommitChanges();
  }
 
  Dts.TaskResult = (int)ScriptResults.Success;
}

Of course there is a lot of room for improvements (proper error-handling, transactional rollback, …).