Using Scripts

Summary

In this post I’m going to show how you can improve developer productivity by steering developers to use scripts where it makes sense.

Setting up IIS

As a back-end developer, I spend a lot of time standing up and configuring new APIs.  One of the tools I use to reduce the amount of man-hours it takes me to get an API up and running is PowerShell.  Personally, the world “PowerShell” makes my skin crawl.  Why?  Because it’s a scripting language that has a syntax that feels like something built by Dr. Frankenstein.  To get beyond my lack of memorizing each and every syntax nuance of PowerShell, I use a lot of Google searches.  Fortunately, after several years of use, I’ve become familiar with some of the capabilities of PowerShell and I can save a lot of time when I create IIS sites.

Now you’re probably wondering where I save my time, since the script has to be written and the site only needs to be setup once.  The time saving comes when I have to change something minor or I have to establish the site on another environment.  In the case of another environment, I can change the path name or url to match the destination environment and run my script to create all the pieces necessary to run my API.

Before I get into the script, I’m going to go through the steps to create an IIS site for WebApi for .Net Core 2.0.

Step 1: Setup the Application Pool.

  • Open IIS and navigate to the Application Pool node.
  • Right-click and add.
  • Give your app pool a name that matches your site, so you can identify it quickly.  This will save you troubleshooting time.
  • For .Net Core, you need to set the .Net Framework Version to “No Managed Code”

Step 2: Setup IIS site.

  • Right-click on the “Sites” node and “Add Web Site”
  • I usually name my site the same as the URL or at least the sub-domain of the URL so I can find it quick.  Again, this name is not used by the system, it is only used when I have to troubleshoot and saving time troubleshooting is the number one priority.
  • Set the path to point to the root of your publish directory (make sure you have done a local publish from Visual Studio before performing this step).
  • Type in the host name.  This is the URL of your site.  If you are just testing locally, you can make up a URL that you’ll need to add to the Hosts file.
  • Select the Application Pool that you created earlier.

Step 3: Optional, setup Hosts file.  Use this step if you are setting up a local website for testing purposes only.

  • Navigate to C:\Windows\System32\drivers\etc
  • Edit “Hosts” file.  You might have to edit with Administrator rights.
  • Add your URL to the hosts file: “127.0.0.1       MyDotNetWebApi.com”

Now try to visualize performing this process for each environment that your company uses.  For me, that comes out to be about half a dozen environments.  In addition to this, each developer that will need your API setup on their PC will need to configure this.  Here’s where the time-saving comes in.  Create the PowerShell script first, and test the script.  Never create the site by hand.  Then use the script for each environment.  Provide the script for other developers to setup their own local copy.  This can be accomplished by posting the script on a wiki page or checking the script into your version control system with the code.

Here’s what an example PowerShell script would look like:

# if you get an error when executing this script, comment the line below to exclude the WebAdministration module
Import-Module WebAdministration

#setup all IIS sites here
$iisAppList = 
    "MyDotNetWebApi,MyDotNetWebApi.franksurl.com,c:\myapicodedirectory,", # use "v4.0" for non-core apps
    "testsite2,testsite2.franksurl.com,c:\temp,v4.0"
    


# setup the app pools and main iis websites
foreach ($appItem in $iisAppList)
{
    $temp = $appItem.split(',')
    
    $iisAppName = $temp[0]
    $iisUrl = $temp[1]
    $iisDirectoryPath = $temp[2]
    $dotNetVersion = $temp[3]
    
    #navigate to the app pools root
    cd IIS:\AppPools\

    if (!(Test-Path $iisAppName -pathType container))
    {
        #create the app pool
        $appPool = New-Item $iisAppName
        $appPool | Set-ItemProperty -Name "managedRuntimeVersion" -Value $dotNetVersion
    }
    
    
    #navigate to the sites root
    cd IIS:\Sites\
    
    if (!(Test-Path $iisAppName -pathType container))
    {
        #create the site
        $iisApp = New-Item $iisAppName -bindings @{protocol="http";bindingInformation=":80:" + $iisUrl} -physicalPath $iisDirectoryPath
        $iisApp | Set-ItemProperty -Name "applicationPool" -Value $iisAppName
        
        Write-Host $iisAppName "completed."
    }
}

c:

You can change the sites listed in the list of sites at the top of the script.  The app pool is setup first, followed by the IIS web site.  Each section will test to see if the app pool or site is already setup (in which is skips).  So you can run the PowerShell script again without causing errors.  Keep the script in a safe location, then you can add to the list and re-run the PowerShell script.  If you need to recreate your environment, you can create all sites with one script.

If you delete all your IIS sites and app pools you might run into the following error:

New-Item : Index was outside the bounds of the array.

To fix this “issue” create a temporary web site in IIS (just use a dummy name like “test”).  Run the script, then delete the dummy site and it’s app pool.  The error is caused by a bug where IIS is trying to create a new site ID.

Setting a Directory to an Application

There are time when you need to convert a directory in your website into it’s own application.  To do this in IIS, you would perform the following steps:

  • Expand the website node
  • Right-click on the directory that will be converted and select “Convert to Application”
  • Click “OK”

To perform this operation automatically in a script, add the following code after creating your IIS sites above (just before the “c:” line of code):

$iisAppList = 
    "MyDotNetWebApi,MyAppDirectory,MyAppDirectory,MyDotNetWebApi\MyAppDirectory,"

foreach ($appItem in $iisAppList)
{
    $temp = $appItem.split(',')

    $iisSiteName = $temp[0]
    $iisAppName = $temp[1]
    $iisPoolName = $temp[2]
    $iisPath = $temp[3]
    $dotNetVersion = $temp[4]

    cd IIS:\AppPools\

    if (!(Test-Path $iisPoolName -pathType container))
    {
        #create the app pool
        $appPool = New-Item $iisPoolName
        $appPool | Set-ItemProperty -Name "managedRuntimeVersion" -Value $dotNetVersion
    }

    cd IIS:\Sites\
    
    # remove and re-apply any IIS applications
    if (Get-WebApplication -Site $iisSiteName -Name $iisAppName)
    {
        Remove-WebApplication -Site $iisSiteName -Name $iisAppName
    }

    ConvertTo-WebApplication -PSPath $iisPath -ApplicationPool $iisPoolName
}

Now add any applications to the list.  The first parameter is the name of the IIS site.  The second parameter is the application name.  The third parameter is the pool name (this script will create a new pool for the application).  The fourth parameter is the path to the folder.  The last parameter is the .Net version (use v4.0 if this application is not a .Net Core project).

For the above script to run, you’ll need to create a blank directory called: C:\myapicodedirectory\MyAppDirectory

Now execute the script and notice that the MyAppDirectory has been turned into an application:

You can add as many applications to each IIS website as you need by adding to the list.

What the code above does is it creates an application pool first (if it doesn’t exist already).  Then it removes the application from the site followed by converting a directory to an application for a specific site.  This script can also be executed multiple times without causing duplicates or errors.

If you run into problems executing your script, you might have to run under an Administrator.  I usually startup powershell in Administrator mode.  Then I navigate to the directory containing the script.  Last, I execute the script.  This allows me to see any errors in the console window.  If you right-click on the ps1 file and run with powershell, your script could fail and exit before you can read the error message.

Feel free to copy the scripts from above and build your own automated installation scripts.

Leave a Reply