Automating IIS actions with PowerShell – Create Multiple Sites

I’m working towards a more complex SignalR based post, but in the mean time part of the work on that involves setting up a few ASP.NET web apps.

If you’re after a more comprehensive guide check out this post on learn.iis.net by Thomas Deml. I’ve summarised the steps required to get some basic .NET 4 web applications deployed.

Objective
To create N identical websites in local IIS, each with an incrementing name Id. Each linked to the same application directory. The exact reason as to why will come in a future post, for now consider it an exercise in manipulating IIS via PowerShell.

s1.site.local
s2.site.local

Step 1 – Ensure you’re running the scripts in x86 mode.

Which seems quite common a problem, with a stackoverflow question. I haven’t worked a way around this yet, but this is the error when not running as x86:

New-Item : Cannot retrieve the dynamic parameters for the cmdlet. Retrieving the COM class factory for component with CLSID {688EEEE5-6A7E-422F-B2E1-6AF00DC944A6} failed due to the following error: 80040154.
At line:1 char:9
+ New-Item <<<< AppPools\test-app-pool
+ CategoryInfo : InvalidArgument: (:) [New-Item], ParameterBindingException
+ FullyQualifiedErrorId : GetDynamicParametersException,Microsoft.PowerShell.Commands.NewItemCommand

Step 2 – Import-Module WebAdministration
This loads the IIS namespace which allows you to just navigate in the same way you would the filesystem

> CD IIS:\

Step 3 – Create & Configure App Pool

    New-Item AppPools\test.pool

    Set-ItemProperty IIS:\AppPools\test.pool -name "enable32BitAppOnWin64" -Value "true"

    Set-ItemProperty IIS:\AppPools\test.pool -name "managedRuntimeVersion" -Value "v4.0"

NOTE: here I didn’t have any luck storing the app pool path in a variable then using Set-ItemProperty, hence the repeating.

Step 4 – Variables

    $sitesToCreate = 10
    $path = "C:\dev\project-x\App.Web"
    $appPool = "test.pool"

Step 5 – Create Site & Link AppPool Loop

For N(10) to zero:

  • Create a new site
  • Set binding info and physical path
  • Set the app pool
    while ($sitesToCreate -gt 0)
    { 
        $siteName = "s" + $sitesToCreate + ".site.local"
        $siteWithIISPrefix = "IIS:\Sites\" + $siteName
        Write-Host "Creating: " $siteName
        
        $site = New-Item $siteWithIISPrefix -bindings @{protocol="http";bindingInformation="*:80:" + $siteName } -physicalPath $path
        
        Set-ItemProperty IIS:\Sites\$siteName -name applicationPool -value $appPool
        $sitesToCreate--
    }

Note: ‘appPool’ is a text variable, not the ‘Get-Item’. Set-ItemProperty operates on a path not a variable representing the item.

We’re done

One last note, to get these to resolve correctly on your local developer machine you’ll need to modify your hosts file.

IIS multisite

The complete code up as a Github Gist.

PowerShell Recursive Rename for an SVN directory

On a large repository, I was attempting to rename the SVN tracking folders that are nested at every directory level, I needed to do this because of a difference in the leading character ‘.’ (period) vs ‘_’ (underscore). I know this could have easily been resolved with a new fetch but I wanted to avoid a lengthy download over a VPN connection.

I thought I would just quickly list some PowerShell commands I was playing with to clean up the repository as a blog post.

The closest I got to a solution but with a lot of errors/warnings during the process was:

Get-ChildItem * -Recurse -force | Where-Object { $_.Mode -eq "d--h-" } | Rename-Item -force -newname '_svn'

It seems the -force parameter was required. I’m not sure why it errors but it still works. Further investigation would be around how many times the commands run per directory, possibly too many times. Another avenue for investigation is the -silent parameter but that’s likely only going to obscure any issues.

Just for reference here’s what else I tried, these did not succeed.

Get-Childitem -path . -include .svn -recurse | Rename-Item -newname {$_.name -replace '.svn','_svn'}
Get-Childitem -path . -include .svn -recurse | foreach { Rename-Item .svn _svn }
Get-Childitem -path . -recurse -include '.svn' | foreach { Rename-Item .svn _svn }
Get-Childitem -path . -recurse | rename-item -newname { $_.name -replace '.svn','_svn' }
Get-Childitem -path . -recurse -include .svn | move-item -destination _svn

If you’re a PowerShell expert feel free to correct my possibly misguided attempt at a recursive rename.

Update 29th Dec 2011
I stumbled upon someone much more clever undertaking a similar rename process. In this case jQuery text, but the logic serves the same purpose it goes and renames content of the files that logic can be replaced with the move-item command.

$find = 'jquery-1\.4\.4'
$replace = 'jquery-1\.5\.1'
$match = '*.cshtml' , '*.vbhtml'
$preview = $true

foreach ($sc in dir -recurse -include $match | where { test-path $_.fullname -pathtype leaf} ) {
    select-string -path $sc -pattern $find
    if (!$preview) {
       (get-content $sc) | foreach-object { $_ -replace $find, $replace } | set-content $sc
    }
}

A Look Back at Discovering PowerShell

This is part 1 of a 3 part series, in which I will be creating a PowerShell script that accepts as input a folder location via a standard windows popup dialog and then performs some repetitive action. I’ll get to the details in the next post where I actually build the script. In the 3rd post will be putting it to use…

But first some background on PowerShell and some details on my awkward attachment to it, back in December 2007 I attended a Readify (RDN) session about PowerShell presented by Mitch Denny and was blown away by its potential and power, along with an attention grabbing demo of it running a Space Invaders game. I proceeded to adapt his demo and do my own investigation and the following month demonstrated the PowerShell concepts internally to my colleagues who specialise in the .NET development space.

I was trying to promote the use of PowerShell to replace a large collection of batch (.bat) scripts we were using at the time across many projects, to do things ranging from mass source control check-outs/check-ins to building deployments of production packages, yes **shudder**. Sadly more often than not, I did not make time to improve and replace all batch scripts I encountered either through the use of PowerShell or alternate approaches to running a script.

Double checking with this post on the MSDN PowerShell blog, I can confirm that at the time it was the first CTP release of PowerShell 2.0 that got my attention. With my switch now to Windows 7 and currently working on a new laptop it was fantastic to see an already installed out of the box PowerShell, which I simply searched for by typing into my start menu.

A few months back I discovered a site that got my attention again with little tips and video tutorials about using PowerShell, sadly a lot of their videos are no longer available, but I still subscribe to an almost daily newsletter with 1 single tip per day. So for a while I’ve been amassing the emails from PowerShell.com in one of my gmail accounts, labelling them thinking “oh that’s cool tip” but not having the time to test it out. Well the other day the “perfect” tip for a planned task came along to get me cracking on this script and blog posts.

In the next post I’ll be running through its actual creation.