Статьи

Управление IIS7 программно

Я большой сторонник автоматизации и автоматизации как можно большей части системы. Я хотел бы убедиться, что сотрудники, не являющиеся разработчиками, могут работать эффективно и постараться сделать как можно больше, чтобы минимизировать количество блокирующих устройств на их пути. IIS может быть одним из таких блокировщиков. Когда дело доходит до сотрудников, создающих новые сайты и пулы приложений, они иногда могут ошибаться. Чтобы убедиться, что все члены моей команды имеют одинаковую настройку — я пишу сценарий настройки.

Инструмент CI должен быть в состоянии управлять автоматическим внедрением управления конфигурацией в системы. Это просто еще один пример того, как все части среды имеют правильную настройку. Автоматизация этого развертывания означает меньшую вероятность человеческой ошибки. Возможность взаимодействия с IIS означает, что можно запустить простой сценарий для создания требуемой установки — как локально, так и в среде сборки.

Мне удалось создать следующий скрипт Powershell.

import-module WebAdministration

Set-Location IIS:\AppPools

#This will create a new application pool of the name (to be passed as a parameter)
New-Item IIS:\AppPools\DemoAppPool
Set-ItemProperty IIS:\AppPools\DemoAppPool enable32BitAppOnWin64 true

Set-Location IIS:\Sites

#This will set a new website called TestSite (should be passed as a parameter)
#and will point this site at C:\test (should be passed as a parameter)
New-Item iis:\Sites\TestSite -bindings @{protocol="http";bindingInformation=":80:TestSite"} -physicalPath c:\test
Set-ItemProperty IIS:\sites\TestSite -name applicationPool -value DemoAppPool

Сценарий в основном автоматизирует способ создания нового пула приложений, нового сайта и последующего назначения этого пула приложений этому сайту.

Этот сценарий можно было легко запустить из powershell или через строку cmd (которая вызывает powershell). Это скрипт, который отлично работает при условии, что вам нужно запустить его только один раз, так как он не учитывает существующий сайт или пул приложений. Требовалось много рефакторинга. созданный скрипт можно найти ниже. Это гораздо полезнее, так как для настройки нужны параметры.

<#
.SYNOPSIS
    Sets up AppPool and Site in IIS
.DESCRIPTION
	Sets up AppPool and Site in IIS (creating where necessary).  Can also be used to change parameters of existing site, i.e. changing the framework, physical path or enabled for 32bit.
	
	It is possible for a Site to share an AppPool with other sites but note any changes to the AppPool settings (i.e. Enable32 or FrameworkVersion), even if only implied by their defaults, will result in an error being raised and script termination.
	
	Should a Site be moved from one AppPool to another leaving the AppPool empty the AppPool will NOT be removed.  Therefore manual intervention will therefore be required to remove 'zombie' AppPools.
.EXAMPLE
    C:\PS> ./iis-site-creation.ps1 'TestSite' 'TestAppPool' 'C:\RootOfTestSite'
    Minimal command; sets up 'TestSite' using the app pool 'TestAppPool' using the physical path of C:\RootOfTestSite.
	
	Note 1: Can just run ./iis-site-creation.ps1 and you will be prompted to enter the three mandatory parameters.
	Note 2: These examples presume script is in current directory.
.EXAMPLE
	C:\PS> ./iis-site-creation.ps1 -SiteName 'TestSite' -AppPool 'MyAppPool' -PhysicalPath 'C:\Sites\TestSite' -Enable32 $true -FrameworkVersion 'v4.0'
	Full example with fully qualified parameters including the two optionals.
#>

param(
	[Parameter(
			Mandatory=$true,
			Position=0,
			HelpMessage="Name of the site")]
	[string]
	$SiteName,
	
	[Parameter(
			Mandatory=$true,
			Position=1,
            HelpMessage="Name of the AppPool to use.  (Will be created if doesn't already exist.)")]
	[string]
	$AppPool,
	
	[Parameter(
			Mandatory=$false,
			Position=2,
			HelpMessage="Physical location of site on system.  E.g. c:\src\ottrunk\website")]
	[string]
	$PhysicalPath = '',
	
	[Parameter(
		Mandatory=$false, 
		HelpMessage="If true will use 32Bit even on Win64 systems.  Default is false.")]
	[bool]
	$Enable32 = $false,
	
	[Parameter(
		Mandatory=$false,
		HelpMessage="Sets AppPool's framework version.  Possible values are 'v2.0' (default) or 'v4.0'")]
	[string]
	$FrameworkVersion = "v2.0"
)

function AppPoolExclusiveToSite([string] $appPool, [string] $siteName) {
	[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Web.Administration")
	$iis = New-Object Microsoft.Web.Administration.ServerManager
	@($iis.sites |
		%{ if($_.Name -ne $siteName) { 
			$_.Applications |
				where-object { $_.ApplicationPoolName -eq $appPool } 
			}
		}).Count -eq 0
}

function UpdateAppPool([bool] $allowChange, [bool] $enable32, [string] $frameworkVersion) {
	$currentEnable32 = Get-ItemProperty "IIS:\AppPools\$AppPool" enable32BitAppOnWin64
	$currentFrameworkVersion = Get-ItemProperty "IIS:\AppPools\$AppPool" managedRuntimeVersion
	if($allowChange) {
		Set-ItemProperty "IIS:\AppPools\$AppPool" enable32BitAppOnWin64 $enable32
		Set-ItemProperty "IIS:\AppPools\$AppPool" managedRuntimeVersion $frameworkVersion
	} elseif( ($currentFrameworkVersion -ne $frameworkVersion) -or ($currentEnable32 -ne $enable32) ) {
		throw "Tried to change AppPool but cannot because AppPool is not exclusive to website"
	}
}

Import-Module WebAdministration
 
if(!(Test-Path "IIS:\AppPools\$AppPool")) { 
	New-Item "IIS:\AppPools\$AppPool"
}
$allowChange = !@(AppPoolExclusiveToSite $AppPool $SiteName)
UpdateAppPool $allowChange $Enable32 $FrameworkVersion


if(!(Test-Path "IIS:\Sites\$SiteName")) {
	New-Item "IIS:\Sites\$SiteName" -bindings @{protocol="http";bindingInformation=":80:$SiteName"}
}
Set-ItemProperty "IIS:\Sites\$SiteName" physicalPath $PhysicalPath
Set-ItemProperty "IIS:\Sites\$SiteName" applicationPool $AppPool

Проблемы с этим сценарием начались при запуске в разных версиях ОС. Машины X64 по умолчанию вызывают PowerShell X64 (как и следовало ожидать). При использовании PowerShell X64 возникла следующая ошибка:

Это, конечно, отлично работало в X86 версии PowerShell. Странно, но в PowerShell X86 произошла другая ошибка. Линия

Test-Path IIS: \ AppPools \

Команде не нравилось работать. Это бросило следующую ошибку:

Я столкнулся с дилеммой исправления чего-то, о чем я относительно мало знаю (скрипты powershell) или продолжаю использовать простой скрипт и вручную манипулировать IIS после первоначальной настройки.

Странно, но я решил отказаться от обоих методов и написал консольное приложение на C # для управления IIS. Это заняло у меня половину времени и было очень легко. Эндрю Вестгарт, IIS MVP , ответил мне в твиттере после того, как я сказал, что сделал это

Я мог бы сказать вам, что :-). NET API рок ?

Это было так же просто, как ссылаться на Microsoft.Web.Administration и писать код для этого API. Поскольку это было консольное приложение, оно создавало исполняемый файл, который я мог легко вызвать из TeamCity или с помощью пакетного скрипта для автоматизации локальной машины. Мне не нужно беспокоиться о ExecutionPolicy, что является настоящим бонусом.

Исходный код консольного приложения доступен на моем сайте github. Не стесняйтесь брать его и менять его по своему вкусу. Я также включил оба сценария powershell, как указано выше.