Configuring IIS in PowerShell
Controlling the configuration of IIS always seems to be difficult from an outside view, involving loading the IIS snapin or fighting with config files in obscure locations but (you knew this was coming next, didn't you?) PowerShell to the rescue again.
Fundamental to all of these snippets is the WebAdministration module that you are required to run as admin before you can import.
Once this module is loaded, the Set-Location works for IIS as if it was a drive so you can use Get-ChildItem to find app pools or sites.
Import-Module WebAdministration
Set-Location IIS:\AppPools
Get-ChildItem |
ForEach-Object {
[string]$ApplicationPoolName = $_.Name
Write-Output "Doing stuff with app pool $ApplicationPoolName"
...
}
Config can be read, created or updated using the ItemProperties cmdlets and providing the correct path (and value for updates).
# Turn off app pool restart after 'n' hours
Set-ItemProperty IIS:\AppPools\$ApplicationPoolName -Name Recycling.periodicRestart.time -Value '0.00:00:00'
# Turn on app pool restart at a random time between midnight and 2am.
Clear-ItemProperty IIS:\AppPools\$ApplicationPoolName -Name Recycling.periodicRestart.schedule
[int]$Hour = Get-Random -Maximum 2
[int]$Minutes = Get-Random -Minimum 1 -Maximum 60
[string]$FormattedTime = (New-TimeSpan -Hours $Hour -Minutes $Minutes).ToString("hh\:mm")
New-ItemProperty -Path IIS:\AppPools\$ApplicationPoolName -Name Recycling.periodicRestart.schedule -Value $FormattedTime
Here, I am removing IIS' default app pool recycle and substituting a random recycle time between midnight and 2am. One thing to be careful of is the formatting of dates and timespans in IIS. Turning off the restart, I had assumed I could set the value to be zero but got an invalid cast exception. The fully qualified time ('0.00:00:00') seemed to be the only thing that was accepted for that value. Similarly, setting a specific time for recycle required building a TimeSpan object then using it to format a string that was accepted by the periodicRestart.schedule value.
Get-ChildItem works equally well for Web sites in IIS.
Set-Location IIS:\Sites
Get-ChildItem | Where-Object { $_.State -eq 'Started' } | ForEach-Object { Stop-Website -Name $_.Name }
Set-Location IIS:\Sites
Get-ChildItem | Where-Object { $_.State -eq 'Stopped' } | ForEach-Object { Start-Website -Name $_.Name }