Last active
August 8, 2024 10:29
-
-
Save davidlu1001/44df18098205ea111adfba014d79af5d to your computer and use it in GitHub Desktop.
IIS Application Pool Management
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[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