Skip to content

Instantly share code, notes, and snippets.

@davidlu1001
Last active August 8, 2024 10:29
Show Gist options
  • Save davidlu1001/44df18098205ea111adfba014d79af5d to your computer and use it in GitHub Desktop.
Save davidlu1001/44df18098205ea111adfba014d79af5d to your computer and use it in GitHub Desktop.
IIS Application Pool Management
[CmdletBinding()]
param(
[Parameter(Mandatory=$false)]
[string]$iisAppPoolPattern = "LoanAlterations*",
[Parameter(Mandatory=$false)]
[string]$computerName = $env:COMPUTERNAME,
[Parameter(Mandatory=$false)]
[int]$maxWaitTime = 30,
[Parameter(Mandatory=$false)]
[switch]$restart,
[Parameter(Mandatory=$false)]
[switch]$recycle,
[Parameter(Mandatory=$false)]
[string]$logFilePath = "C:\temp\scripts\IISAppPoolManagement.log"
)
# Enable strict mode for better error handling
Set-StrictMode -Version Latest
# Set error action preference to stop script execution on error
$ErrorActionPreference = 'Stop'
# Function to write log messages
function Write-Log {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[string]$Message,
[Parameter(Mandatory=$false)]
[ValidateSet("INFO", "WARNING", "ERROR")]
[string]$Level = "INFO"
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$logMessage = "[$timestamp] [$Level] $Message"
# Write to console with appropriate color
switch ($Level) {
"INFO" { Write-Host $logMessage -ForegroundColor Green }
"WARNING" { Write-Host $logMessage -ForegroundColor Yellow }
"ERROR" { Write-Host $logMessage -ForegroundColor Red }
}
# Append to log file
try {
Add-Content -Path $logFilePath -Value $logMessage -ErrorAction Stop
} catch {
Write-Warning "Failed to write to log file: $_"
}
}
# Function to create a consistent result object
function New-ResultObject {
param (
[string]$AppPoolName,
[string]$InitialState,
[string]$RestartStatus = "Not Attempted",
[string]$RecycleStatus = "Not Attempted",
[string]$FinalState
)
return [PSCustomObject]@{
AppPoolName = $AppPoolName
InitialState = $InitialState
RestartStatus = $RestartStatus
RecycleStatus = $RecycleStatus
FinalState = $FinalState
}
}
# Function to manage IIS application pools locally
function Manage-LocalIISAppPools {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[string]$pattern,
[Parameter(Mandatory=$true)]
[bool]$isRestart,
[Parameter(Mandatory=$true)]
[bool]$isRecycle,
[Parameter(Mandatory=$true)]
[int]$maxWait
)
try {
# Check if WebAdministration module is available
if (-not (Get-Module -ListAvailable -Name WebAdministration)) {
throw "WebAdministration module is not available. Please ensure IIS is installed."
}
Import-Module WebAdministration -ErrorAction Stop
} catch {
Write-Log "Failed to import WebAdministration module. Error: $_" -Level "ERROR"
return $null
}
$appPools = Get-ChildItem IIS:\AppPools | Where-Object { $_.Name -like $pattern }
if (-not $appPools) {
Write-Log "No application pools matching the pattern '$pattern' were found." -Level "WARNING"
return $null
}
$results = @()
foreach ($appPool in $appPools) {
$result = New-ResultObject -AppPoolName $appPool.Name -InitialState $appPool.State -FinalState $appPool.State
if ($isRestart) {
try {
Write-Log "Restarting Application Pool: $($appPool.Name)"
if ($appPool.State -eq "Started") {
Stop-WebAppPool -Name $appPool.Name -ErrorAction Stop
}
Start-WebAppPool -Name $appPool.Name -ErrorAction Stop
# Wait for the app pool to start
$waited = 0
do {
Start-Sleep -Seconds 1
$waited++
$appPool = Get-Item "IIS:\AppPools\$($appPool.Name)"
} while (($appPool.State -ne "Started") -and ($waited -lt $maxWait))
if ($appPool.State -eq "Started") {
$result.RestartStatus = "Success"
Write-Log "Application Pool restarted successfully: $($appPool.Name)"
} else {
$result.RestartStatus = "Failed to start within $maxWait seconds"
Write-Log "Application Pool failed to start within $maxWait seconds: $($appPool.Name)" -Level "ERROR"
# Skip recycling if restart failed
$isRecycle = $false
}
} catch {
$result.RestartStatus = "Failed: $_"
Write-Log "Failed to restart Application Pool: $($appPool.Name). Error: $_" -Level "ERROR"
# Skip recycling if restart failed
$isRecycle = $false
}
}
if ($isRecycle) {
try {
Write-Log "Recycling Application Pool: $($appPool.Name)"
$appPool.Recycle()
# Wait for recycle to complete
Start-Sleep -Seconds 5
# Get the updated state
$appPool = Get-Item "IIS:\AppPools\$($appPool.Name)"
$result.RecycleStatus = "Success"
Write-Log "Application Pool recycled successfully: $($appPool.Name)"
} catch {
$result.RecycleStatus = "Failed: $_"
Write-Log "Failed to recycle Application Pool: $($appPool.Name). Error: $_" -Level "ERROR"
}
}
# Get the final state
$appPool = Get-Item "IIS:\AppPools\$($appPool.Name)"
$result.FinalState = $appPool.State
$results += $result
}
return $results
}
# Function to manage IIS application pools remotely
function Manage-RemoteIISAppPools {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[string]$computerName,
[Parameter(Mandatory=$true)]
[string]$pattern,
[Parameter(Mandatory=$true)]
[bool]$isRestart,
[Parameter(Mandatory=$true)]
[bool]$isRecycle,
[Parameter(Mandatory=$true)]
[int]$maxWait
)
$remoteScript = {
param($p)
# Import WebAdministration module
Import-Module WebAdministration -ErrorAction Stop
# Function to create a consistent result object
function New-ResultObject {
param (
[string]$AppPoolName,
[string]$InitialState,
[string]$RestartStatus = "Not Attempted",
[string]$RecycleStatus = "Not Attempted",
[string]$FinalState
)
return [PSCustomObject]@{
AppPoolName = $AppPoolName
InitialState = $InitialState
RestartStatus = $RestartStatus
RecycleStatus = $RecycleStatus
FinalState = $FinalState
}
}
$appPools = Get-ChildItem IIS:\AppPools | Where-Object { $_.Name -like $p.pattern }
if (-not $appPools) {
Write-Output "WARNING: No application pools matching the pattern '$($p.pattern)' were found."
return $null
}
$results = @()
foreach ($appPool in $appPools) {
$result = New-ResultObject -AppPoolName $appPool.Name -InitialState $appPool.State -FinalState $appPool.State
if ($p.isRestart) {
try {
Write-Output "INFO: Restarting Application Pool: $($appPool.Name)"
if ($appPool.State -eq "Started") {
Stop-WebAppPool -Name $appPool.Name -ErrorAction Stop
}
Start-WebAppPool -Name $appPool.Name -ErrorAction Stop
# Wait for the app pool to start
$waited = 0
do {
Start-Sleep -Seconds 1
$waited++
$appPool = Get-Item "IIS:\AppPools\$($appPool.Name)"
} while (($appPool.State -ne "Started") -and ($waited -lt $p.maxWait))
if ($appPool.State -eq "Started") {
$result.RestartStatus = "Success"
Write-Output "INFO: Application Pool restarted successfully: $($appPool.Name)"
} else {
$result.RestartStatus = "Failed to start within $($p.maxWait) seconds"
Write-Output "ERROR: Application Pool failed to start within $($p.maxWait) seconds: $($appPool.Name)"
# Skip recycling if restart failed
$p.isRecycle = $false
}
} catch {
$result.RestartStatus = "Failed: $_"
Write-Output "ERROR: Failed to restart Application Pool: $($appPool.Name). Error: $_"
# Skip recycling if restart failed
$p.isRecycle = $false
}
}
if ($p.isRecycle) {
try {
Write-Output "INFO: Recycling Application Pool: $($appPool.Name)"
$appPool.Recycle()
# Wait for recycle to complete
Start-Sleep -Seconds 5
$appPool = Get-Item "IIS:\AppPools\$($appPool.Name)"
$result.RecycleStatus = "Success"
Write-Output "INFO: Application Pool recycled successfully: $($appPool.Name)"
} catch {
$result.RecycleStatus = "Failed: $_"
Write-Output "ERROR: Failed to recycle Application Pool: $($appPool.Name). Error: $_"
}
}
$appPool = Get-Item "IIS:\AppPools\$($appPool.Name)"
$result.FinalState = $appPool.State
$results += $result
}
return $results
}
try {
$params = @{
pattern = $pattern
isRestart = $isRestart
isRecycle = $isRecycle
maxWait = $maxWait
}
$results = Invoke-Command -ComputerName $computerName -ScriptBlock $remoteScript -ArgumentList $params
return $results
} catch {
Write-Log "Failed to execute IIS management on remote server $computerName. Error: $_" -Level "ERROR"
return $null
}
}
# Main execution block
try {
Write-Log "Script started for computer: $computerName"
Write-Log "AppPool pattern: $iisAppPoolPattern"
Write-Log "Operations - Restart: $restart, Recycle: $recycle"
if (-not $restart -and -not $recycle) {
Write-Log "No operation specified. Please use -restart and/or -recycle switch." -Level "ERROR"
exit 1
}
$params = @{
pattern = $iisAppPoolPattern
isRestart = $restart.IsPresent
isRecycle = $recycle.IsPresent
maxWait = $maxWaitTime
}
if ($computerName -eq $env:COMPUTERNAME) {
Write-Log "Executing locally"
$results = Manage-LocalIISAppPools @params
} else {
Write-Log "Executing remotely on $computerName"
$results = Manage-RemoteIISAppPools -computerName $computerName @params
}
if ($null -ne $results) {
$successCount = @($results | Where-Object { $_.RestartStatus -eq "Success" -or $_.RecycleStatus -eq "Success" }).Count
$failCount = @($results | Where-Object { ($_.RestartStatus -ne "Success" -and $_.RestartStatus -ne "Not Attempted") -or ($_.RecycleStatus -ne "Success" -and $_.RecycleStatus -ne "Not Attempted") }).Count
foreach ($result in $results) {
Write-Log "App Pool: $($result.AppPoolName) - Initial State: $($result.InitialState), Restart: $($result.RestartStatus), Recycle: $($result.RecycleStatus), Final State: $($result.FinalState)"
}
Write-Log "IIS Application Pool management completed. Success: $successCount, Failed: $failCount"
if ($failCount -eq 0) {
Write-Log "All requested IIS Application Pool operations completed successfully."
} else {
Write-Log "Some IIS Application Pool operations failed. Please check the logs for details." -Level "WARNING"
}
} else {
Write-Log "No results returned. Check if any matching application pools were found or if there were execution errors." -Level "WARNING"
}
} catch {
Write-Log "An unexpected error occurred: $_" -Level "ERROR"
exit 1
} finally {
Write-Log "Script execution completed."
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment