When working with IIS 7.5+ application pools through PowerShell, many administrators find themselves struggling with inconsistent syntax patterns. While basic settings like identity and pipeline mode work beautifully with object property assignment, recycling schedules force us into less elegant Add-WebConfiguration
or appcmd approaches.
The root of the problem lies in how IIS stores scheduled recycling times. Unlike simple properties, these are stored as collections within the application pool configuration:
$pool = Get-Item IIS:\AppPools\MyAppPool
$pool.recycling.periodicRestart.schedule.Collection.GetType()
# Shows System.Configuration.ConfigurationElementCollection
Here are three production-tested approaches that maintain clean PowerShell syntax:
Method 1: Using Clear() and Add()
$pool = Get-Item IIS:\AppPools\MyAppPool
$pool.recycling.periodicRestart.schedule.Collection.Clear()
$pool.recycling.periodicRestart.schedule.Collection.Add("01:30:00")
$pool.recycling.periodicRestart.schedule.Collection.Add("12:00:00")
$pool | Set-Item
Method 2: Leveraging Configuration Attributes
$pool = Get-WebAppPool -Name "MyAppPool"
$pool.recycling.periodicRestart.schedule.Attributes["value"].Value = @("01:30:00","12:00:00")
$pool | Set-Item
Method 3: Creating Extension Functions
function Add-RecycleSchedule {
param(
[Parameter(Mandatory=$true)]
[string]$AppPoolName,
[Parameter(Mandatory=$true)]
[string[]]$Times
)
$pool = Get-WebAppPool -Name $AppPoolName
$pool.recycling.periodicRestart.schedule.Attributes["value"].Value = $Times
$pool | Set-Item
}
Add-RecycleSchedule -AppPoolName "CriticalApp" -Times @("02:00:00", "14:00:00")
When working with PowerShell's New-TimeSpan
, remember to convert to the IIS expected format:
$time = New-TimeSpan -Hours 1 -Minutes 30
$formattedTime = "{0:hh\:mm\:ss}" -f $time
$pool.recycling.periodicRestart.schedule.Collection.Add($formattedTime)
Here's how to apply consistent schedules across multiple pools:
$pools = @("WebApp1", "WebApp2", "WebApiPool")
$recycleTimes = @("01:00:00", "13:00:00")
foreach ($poolName in $pools) {
$pool = Get-WebAppPool -Name $poolName
$pool.recycling.periodicRestart.schedule.Attributes["value"].Value = $recycleTimes
$pool | Set-Item
}
After configuration, verify settings with:
Get-WebAppPool -Name "MyAppPool" |
Select-Object -ExpandProperty Recycling |
Select-Object -ExpandProperty periodicRestart |
Select-Object -ExpandProperty schedule
When automating IIS 7.5/8.0 configurations via PowerShell, many administrators find themselves stuck between two undesirable approaches:
# The verbose method:
Set-ItemProperty 'IIS:\\AppPools\\DemoPool' -Name recycling.periodicRestart.time -Value "01:30:00"
# The configuration-heavy method:
Add-WebConfiguration -Filter "system.applicationHost/applicationPools" -Value @{recycling=@{periodicRestart=@{time="01:30:00"}}}
Here's how I prefer to handle Application Pool configuration in PowerShell:
$pool = Get-Item IIS:\\AppPools\\MyAppPool
$pool.processModel.identityType = "SpecificUser"
$pool.processModel.userName = "domain\\user"
$pool.processModel.password = "password"
$pool.managedRuntimeVersion = "v4.0"
$pool | Set-Item
The stumbling block comes when trying to configure recycling schedules with this clean syntax. The straightforward attempt:
$pool.recycling.periodicRestart.schedule = (New-TimeSpan -Hours 1 -Minutes 30)
Fails because the schedule property is actually a collection that requires special handling.
After much experimentation, here's the cleanest method I've found:
$pool = Get-Item IIS:\\AppPools\\MyAppPool
$recycling = $pool.Recycling
$periodicRestart = $recycling.periodicRestart
# Clear existing schedules if needed
$periodicRestart.scheduleCollection.Clear()
# Add new schedules
$periodicRestart.scheduleCollection.Add("01:30:00")
$periodicRestart.scheduleCollection.Add("12:00:00")
$pool | Set-Item
Putting it all together:
$appPools = @("ProductionPool", "StagingPool", "TestPool")
$recycleTimes = @("01:30:00", "12:00:00", "18:00:00")
foreach ($poolName in $appPools) {
$pool = New-WebAppPool -Name $poolName -Force
# Basic configuration
$pool.processModel.identityType = "SpecificUser"
$pool.processModel.userName = "domain\\user"
$pool.processModel.password = "password"
$pool.managedRuntimeVersion = "v4.0"
# Recycling configuration
$periodicRestart = $pool.recycling.periodicRestart
$periodicRestart.scheduleCollection.Clear()
foreach ($time in $recycleTimes) {
$periodicRestart.scheduleCollection.Add($time)
}
# Configure other recycling settings
$periodicRestart.memory = 0 # Disable memory-based recycling
$periodicRestart.privateMemory = 0
$pool | Set-Item
}
For those who need to work with existing app pools:
function Set-AppPoolRecycling {
param(
[string]$appPoolName,
[string[]]$recycleTimes
)
$pool = Get-Item "IIS:\\AppPools\\$appPoolName"
$schedule = $pool.recycling.periodicRestart.schedule
# Convert to collection for manipulation
$scheduleColl = $pool.recycling.periodicRestart.scheduleCollection
$scheduleColl.Clear()
foreach ($time in $recycleTimes) {
$scheduleColl.Add($time)
}
$pool | Set-Item
}
# Usage:
Set-AppPoolRecycling -appPoolName "CriticalAppPool" -recycleTimes @("02:00:00", "14:00:00")