Before using ANY examples below, find your actual site names:
# GET YOUR REAL SITE NAMES FIRST:
Get-IISSite | select Name, ID, State
# Example output:
# Name ID State
# ---- -- -----
# Default Web Site 1 Started
# MyCompanyAPI 2 Started
# TestPortal 3 Stopped
Throughout this guide:
[YOUR_SITE_NAME]
= Replace with actual site name from above[YOUR_APP_POOL]
= Replace with actual app pool name "Default Web Site"
as a real working exampleQuick Reference:
# Find app pool names:
Get-IISAppPool | select Name
# Find app pool for specific site:
(Get-IISSite "[YOUR_SITE_NAME]").Applications[0].ApplicationPoolName
---
These commands work immediately with ANY IIS server:
# 1. See all your sites
Get-IISSiteInfo
# 2. Check status of first site (usually "Default Web Site")
$firstSite = (Get-IISSite)[0].Name
Get-SiteStatus $firstSite
# 3. Get performance data for first site
Get-SitePerformance $firstSite -Samples 3
# 4. Quick health check for all sites
Get-IISSite | ForEach-Object {
Write-Host "$($_.Name): $($_.State)" -ForegroundColor $(if($_.State -eq "Started"){"Green"}else{"Red"})
}
# 5. Monitor first site for 2 minutes
# (Press Ctrl+C to stop early)
Watch-IISSite $firstSite
After running the Quick Start, replace [YOUR_SITE_NAME]
in examples below with your actual site names.
---
1. [Discovery & Info Functions](#discovery--info-functions)
2. [Website Monitoring Functions](#website-monitoring-functions)
3. [Restart & Recovery Functions](#restart--recovery-functions)
4. [Performance Monitoring](#performance-monitoring)
5. [Log Monitoring Functions](#log-monitoring-functions)
6. [Health Check Functions](#health-check-functions)
7. [Alerting & Notification Functions](#alerting--notification-functions)
8. [Automated Recovery Functions](#automated-recovery-functions)
9. [Bulk Management Functions](#bulk-management-functions)
10. [Real-World Scenarios](#real-world-scenarios)
---
Basic Usage:
# REPLACE "MyWebsite" WITH YOUR ACTUAL SITE NAME
# To find your site names: Get-IISSite | select Name
# Get info for specific site
Get-IISSiteInfo "[YOUR_SITE_NAME]"
# REAL EXAMPLE:
Get-IISSiteInfo "Default Web Site"
# Output:
# SiteName SiteID SiteState PhysicalPath PathExists AppPoolName AppPoolState DotNetVersion Bindings SSL IsResponding TestUrl
# -------- ------ --------- ------------ ---------- ----------- ------------ ------------- -------- --- ------------ -------
# Default Web Site 1 Started C:\inetpub\wwwroot True DefaultAppPool Started v4.0 http:*:80:,https:*:443: True True http://localhost
Advanced Usage:
# Get info for all sites
Get-IISSiteInfo
# Get info for sites matching pattern
Get-IISSiteInfo "*test*" # All sites with "test" in name
Get-IISSiteInfo "*prod*" # All production sites
Get-IISSiteInfo "API*" # All sites starting with "API"
# Example scenarios:
Get-IISSiteInfo "*staging*" # Check all staging environments
Get-IISSiteInfo "*wordpress*" # Find all WordPress sites
Real-World Example:
# Daily morning check - get overview of all sites
Write-Host "=== Daily Site Overview ===" -ForegroundColor Cyan
Get-IISSiteInfo | Where-Object {$_.SiteState -ne "Started" -or !$_.IsResponding} |
Format-Table SiteName, SiteState, IsResponding -AutoSize
# Find sites with path issues
Get-IISSiteInfo | Where-Object {!$_.PathExists} |
Select-Object SiteName, PhysicalPath | Format-Table -AutoSize
Basic Usage:
# REPLACE WITH YOUR ACTUAL SITE NAME
Get-SiteStatus "[YOUR_SITE_NAME]"
# REAL EXAMPLE:
Get-SiteStatus "Default Web Site"
# Output:
# === Site Status: Default Web Site ===
# Site State: Started
# App Pool: DefaultAppPool - Started
# Physical Path: C:\inetpub\wwwroot
# Path Exists: True
# Worker Process: PID 1234 - Memory: 45.2MB
# HTTP Test: 200 - OK
Advanced Usage:
# Check multiple sites in sequence
$criticalSites = @("MainWebsite", "APIService", "PaymentGateway")
foreach($site in $criticalSites) {
Get-SiteStatus $site
Write-Host ""
}
# Use in conditional logic
$status = Get-SiteStatus "MyWebsite" 2>&1
if($LASTEXITCODE -eq 0) {
Write-Host "Site is healthy" -ForegroundColor Green
} else {
Write-Host "Site has issues - investigating..." -ForegroundColor Red
# Trigger recovery actions
}
Real-World Example:
# Morning health check script
function Morning-HealthCheck {
$sites = @("CustomerPortal", "AdminDashboard", "APIGateway", "PaymentService")
Write-Host "Morning Health Check - $(Get-Date -Format 'yyyy-MM-dd HH:mm')" -ForegroundColor Green
Write-Host "=" * 60
foreach($site in $sites) {
try {
Get-SiteStatus $site
Write-Host "ā $site - OK" -ForegroundColor Green
} catch {
Write-Host "ā $site - ISSUES DETECTED" -ForegroundColor Red
# Could trigger alert here
}
Write-Host ""
}
}
Morning-HealthCheck
---
Basic Usage:
# REPLACE WITH YOUR SITE NAME - FIND WITH: Get-IISSite | select Name
Watch-IISSite "[YOUR_SITE_NAME]"
# REAL EXAMPLE:
Watch-IISSite "Default Web Site"
# Output (continuous):
# 2024-07-11 09:15:30 | Check #1 | ā OK | Site:True Pool:True HTTP:True | Response:245ms | Failures:0 | Uptime:00:01:30
# 2024-07-11 09:16:00 | Check #2 | ā OK | Site:True Pool:True HTTP:True | Response:189ms | Failures:0 | Uptime:00:02:00
Advanced Usage:
# Aggressive monitoring with auto-restart
Watch-IISSite "[YOUR_CRITICAL_SITE]" -IntervalSeconds 15 -AlertThreshold 2 -AutoRestart
# REAL EXAMPLES:
Watch-IISSite "Default Web Site" -IntervalSeconds 15 -AlertThreshold 2 -AutoRestart
Watch-IISSite "MyCompanyAPI" -IntervalSeconds 30 -AlertThreshold 3
# Conservative monitoring for stable site
Watch-IISSite "[YOUR_STABLE_SITE]" -IntervalSeconds 300 -AlertThreshold 5
Real-World Examples:
Deployment Monitoring:
# Monitor during deployment
Write-Host "Starting deployment monitoring..." -ForegroundColor Yellow
Write-Host "Deploy your application now, monitoring will detect when it's ready"
# Monitor every 10 seconds during deployment
Watch-IISSite "ProductionAPI" -IntervalSeconds 10 -AlertThreshold 2
# Use case: Monitor while deployment team deploys new version
# Will automatically detect when site comes back online
Production Monitoring:
# Production site with auto-recovery
Write-Host "Starting production monitoring with auto-recovery"
Watch-IISSite "EcommerceStore" -IntervalSeconds 30 -AlertThreshold 3 -AutoRestart
# Critical service monitoring
Watch-IISSite "PaymentProcessor" -IntervalSeconds 15 -AlertThreshold 1 -AutoRestart
Maintenance Window Monitoring:
# Monitor during maintenance
Write-Host "Monitoring during maintenance window..."
Watch-IISSite "MaintenanceSite" -IntervalSeconds 60 -AlertThreshold 10
# Higher threshold during maintenance when temporary failures are expected
Basic Usage:
# Collect 5 samples (default) with 2-second intervals
Get-SitePerformance "MyWebsite"
# Output:
# Time CurrentConnections RequestsPerSec QueueLength CPUPercent MemoryMB
# ---- ------------------ -------------- ----------- ---------- --------
# 14:30:15 25 12.5 0 15.2 145.6
# 14:30:17 23 11.8 0 14.8 146.1
# 14:30:19 27 13.2 1 16.1 145.9
#
# Averages:
# Connections: 25.0
# Requests/Sec: 12.5
# Memory (MB): 145.9
Advanced Usage:
# Extended sampling for detailed analysis
Get-SitePerformance "HighTrafficSite" -Samples 20
# Quick performance check
Get-SitePerformance "APIService" -Samples 3
# Performance comparison
Write-Host "Before optimization:" -ForegroundColor Yellow
Get-SitePerformance "OptimizationTarget" -Samples 10
# Make changes here...
Write-Host "After optimization:" -ForegroundColor Green
Get-SitePerformance "OptimizationTarget" -Samples 10
Real-World Examples:
Load Testing Analysis:
# Monitor during load test
Write-Host "Starting load test monitoring..." -ForegroundColor Cyan
Write-Host "Start your load test now..."
# Collect samples during load test
$beforeLoad = Get-SitePerformance "LoadTestSite" -Samples 5
Write-Host "Baseline established. Start load test now and press Enter when complete."
Read-Host
$duringLoad = Get-SitePerformance "LoadTestSite" -Samples 15
Write-Host "Load test analysis complete."
# Compare results
Write-Host "`nPerformance Comparison:" -ForegroundColor Yellow
Write-Host "Before Load - Avg Memory: $($beforeLoad.MemoryMB | Measure-Object -Average).Average MB"
Write-Host "During Load - Avg Memory: $($duringLoad.MemoryMB | Measure-Object -Average).Average MB"
Performance Baseline:
# Establish performance baseline
function Create-PerformanceBaseline {
param([string]$SiteName)
Write-Host "Creating performance baseline for: $SiteName" -ForegroundColor Green
# Collect samples at different times
$morning = Get-SitePerformance $SiteName -Samples 10
Write-Host "Morning samples collected, waiting 4 hours for afternoon samples..."
Start-Sleep (4 * 60 * 60) # 4 hours
$afternoon = Get-SitePerformance $SiteName -Samples 10
# Save baseline
$baseline = @{
Site = $SiteName
Date = Get-Date
Morning = $morning
Afternoon = $afternoon
}
$baseline | ConvertTo-Json | Out-File "baseline_$($SiteName)_$(Get-Date -f 'yyyyMMdd').json"
Write-Host "Baseline saved to baseline_$($SiteName)_$(Get-Date -f 'yyyyMMdd').json"
}
Create-PerformanceBaseline "ProductionSite"
---
Basic Usage:
# REPLACE WITH YOUR SITE NAME
Restart-IISSiteComplete "[YOUR_SITE_NAME]"
# REAL EXAMPLE:
Restart-IISSiteComplete "Default Web Site"
# Output:
# Restart site 'Default Web Site' and app pool? (y/N): y
# Starting restart sequence for: Default Web Site
# Stopping site...
# Site stopped
# Restarting application pool: DefaultAppPool...
# App pool restarted
# Waiting 3 seconds...
# Starting site...
# Site started
# ā Restart completed successfully
# ā HTTP test successful: 200
Advanced Usage:
# Force restart without confirmation (USE YOUR REAL SITE NAME)
Restart-IISSiteComplete "[YOUR_SITE_NAME]" -Force
# REAL EXAMPLES:
Restart-IISSiteComplete "Default Web Site" -Force
Restart-IISSiteComplete "MyCompanyAPI" -RestartAppPool $false -Force # Site only, not app pool
# Restart site only (don't restart app pool)
Restart-IISSiteComplete "[YOUR_SITE_NAME]" -RestartAppPool $false -Force
# Custom wait time
Restart-IISSiteComplete "[YOUR_SLOW_SITE]" -WaitSeconds 10 -Force
Real-World Examples:
Deployment Restart:
# Post-deployment restart sequence
Write-Host "Post-deployment restart sequence starting..." -ForegroundColor Cyan
$sites = @("WebAPI", "CustomerPortal", "AdminDashboard")
foreach($site in $sites) {
Write-Host "Restarting $site..." -ForegroundColor Yellow
try {
Restart-IISSiteComplete $site -Force -WaitSeconds 5
Write-Host "ā $site restarted successfully" -ForegroundColor Green
} catch {
Write-Host "ā Failed to restart $site`: $($_.Exception.Message)" -ForegroundColor Red
}
}
Write-Host "Deployment restart sequence completed" -ForegroundColor Cyan
Emergency Restart:
# Emergency restart for unresponsive site
Write-Host "EMERGENCY RESTART INITIATED" -ForegroundColor Red -BackgroundColor White
# Try graceful restart first
try {
Restart-IISSiteComplete "UnresponsiveSite" -Force -WaitSeconds 1
Write-Host "Graceful restart successful" -ForegroundColor Green
} catch {
Write-Host "Graceful restart failed, trying aggressive recovery..." -ForegroundColor Yellow
# Force stop everything
Stop-IISSite "UnresponsiveSite" -ErrorAction SilentlyContinue
Stop-WebAppPool "UnresponsiveAppPool" -ErrorAction SilentlyContinue
# Kill worker processes if needed
Get-Process w3wp -ErrorAction SilentlyContinue | Where-Object {$_.MainWindowTitle -like "*UnresponsiveAppPool*"} | Stop-Process -Force
Start-Sleep 5
# Restart
Start-WebAppPool "UnresponsiveAppPool"
Start-IISSite "UnresponsiveSite"
Write-Host "Aggressive restart completed" -ForegroundColor Yellow
}
Scheduled Maintenance:
# Scheduled maintenance restart
function Invoke-MaintenanceRestart {
$maintenanceWindow = @{
Start = "02:00"
End = "04:00"
}
$currentTime = Get-Date -Format "HH:mm"
if($currentTime -ge $maintenanceWindow.Start -and $currentTime -le $maintenanceWindow.End) {
Write-Host "Maintenance window active - performing restarts" -ForegroundColor Green
$productionSites = Get-IISSite | Where-Object {$_.Name -like "*prod*"}
foreach($site in $productionSites) {
Write-Host "Maintenance restart: $($site.Name)"
Restart-IISSiteComplete $site.Name -Force -WaitSeconds 10
}
} else {
Write-Host "Outside maintenance window ($($maintenanceWindow.Start)-$($maintenanceWindow.End)) - restart cancelled" -ForegroundColor Yellow
}
}
Invoke-MaintenanceRestart
Basic Usage:
# Restart app pool by site name
Restart-AppPoolOnly -SiteName "MyWebsite"
# Restart app pool directly
Restart-AppPoolOnly -AppPoolName "MyAppPool"
# Output:
# Restarting application pool: MyAppPool
# Current state: Started
# New state: Started
# ā Worker process started: PID 5678
Advanced Usage:
# Restart multiple app pools
$appPools = @("APIPool", "WebPool", "ServicePool")
foreach($pool in $appPools) {
Write-Host "Restarting $pool..." -ForegroundColor Yellow
Restart-AppPoolOnly -AppPoolName $pool
}
# Restart app pool for site without affecting site state
$sites = Get-IISSite | Where-Object {$_.Name -like "*microservice*"}
foreach($site in $sites) {
Write-Host "Recycling app pool for: $($site.Name)"
Restart-AppPoolOnly -SiteName $site.Name
}
Real-World Examples:
Memory Pressure Relief:
# Monitor and restart high-memory app pools
$memoryThreshold = 1000 # MB
$highMemoryPools = Get-Process w3wp -ErrorAction SilentlyContinue | Where-Object {
($_.WorkingSet / 1MB) -gt $memoryThreshold
} | ForEach-Object {
# Extract app pool name from command line
$cmdLine = (Get-WmiObject -Query "SELECT CommandLine FROM Win32_Process WHERE ProcessId=$($_.Id)").CommandLine
if($cmdLine -match '-ap "([^"]+)"') {
$matches[1]
}
} | Select-Object -Unique
foreach($poolName in $highMemoryPools) {
Write-Host "High memory usage detected in: $poolName - Restarting..." -ForegroundColor Yellow
Restart-AppPoolOnly -AppPoolName $poolName
}
Development Environment Reset:
# Reset all development app pools
Write-Host "Resetting development environment..." -ForegroundColor Cyan
Get-IISAppPool | Where-Object {$_.Name -like "*dev*" -or $_.Name -like "*test*"} | ForEach-Object {
Write-Host "Recycling: $($_.Name)" -ForegroundColor Yellow
Restart-AppPoolOnly -AppPoolName $_.Name
}
Write-Host "Development environment reset complete" -ForegroundColor Green
Basic Usage:
# Smart recovery with progressive escalation
Invoke-SiteRecovery "ProblematicSite"
# Output:
# Starting recovery process for: ProblematicSite
# Attempting: Reset App Pool Failures...
# Attempting: Start App Pool...
# Attempting: Start Site...
# ā Recovery successful with: Start Site
# Final status - Site: Started, Pool: Started
Advanced Usage:
# Recovery with custom test URL
Invoke-SiteRecovery "CustomAPI" -TestUrl "http://localhost/api/health"
# Use in automated monitoring
$recoverySuccess = Invoke-SiteRecovery "CriticalService"
if(!$recoverySuccess) {
Write-Host "Automatic recovery failed - escalating to operations team" -ForegroundColor Red
# Send alert to operations team
}
Real-World Examples:
Automated Recovery Script:
# Automated recovery for multiple sites
function Invoke-MassRecovery {
param([string[]]$SiteNames)
$results = @()
foreach($siteName in $SiteNames) {
Write-Host "Attempting recovery for: $siteName" -ForegroundColor Cyan
$startTime = Get-Date
$success = Invoke-SiteRecovery $siteName
$duration = (Get-Date) - $startTime
$results += [PSCustomObject]@{
Site = $siteName
Success = $success
Duration = $duration.TotalSeconds
Timestamp = $startTime
}
if($success) {
Write-Host "ā $siteName recovered in $([math]::Round($duration.TotalSeconds,1))s" -ForegroundColor Green
} else {
Write-Host "ā $siteName recovery failed after $([math]::Round($duration.TotalSeconds,1))s" -ForegroundColor Red
}
}
return $results
}
# Use during mass outage
$problematicSites = @("Site1", "Site2", "Site3")
$recoveryResults = Invoke-MassRecovery $problematicSites
# Generate report
$recoveryResults | Format-Table -AutoSize
Health Check with Recovery:
# Check health and recover if needed
function Monitor-AndRecover {
param([string]$SiteName)
Write-Host "Monitoring: $SiteName" -ForegroundColor White
# Test site health
try {
$response = Invoke-WebRequest "http://localhost" -UseBasicParsing -TimeoutSec 5
if($response.StatusCode -eq 200) {
Write-Host "ā $SiteName is healthy" -ForegroundColor Green
return $true
}
} catch {
Write-Host "ā $SiteName is unresponsive - starting recovery..." -ForegroundColor Yellow
$recovered = Invoke-SiteRecovery $SiteName
if($recovered) {
Write-Host "ā $SiteName recovered successfully" -ForegroundColor Green
return $true
} else {
Write-Host "ā $SiteName recovery failed - manual intervention required" -ForegroundColor Red
return $false
}
}
}
# Monitor critical sites
$criticalSites = @("PaymentGateway", "UserAuth", "MainAPI")
foreach($site in $criticalSites) {
Monitor-AndRecover $site
}
---
Basic Usage:
# Real-time dashboard with default 5-second refresh
Show-SitePerformanceDashboard "MyWebsite"
# Output (refreshes every 5 seconds):
# āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
# ā IIS PERFORMANCE DASHBOARD ā
# ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā£
# ā Site: MyWebsite ā
# ā Time: 2024-07-11 14:35:22 ā
# āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
#
# STATUS:
# Site State: Started
# Pool State: Started
#
# PERFORMANCE:
# Current Connections: 45
# Requests/Second: 23.5
# Request Queue: 0
#
# WORKER PROCESS:
# Process ID: 1234
# Memory Usage: 234.5 MB
# Uptime: 2d 5h 32m
# CPU Usage: 12.3%
#
# HTTP TEST:
# Status: 200 - OK
# Response Time: 156ms
Advanced Usage:
# Faster refresh for real-time monitoring
Show-SitePerformanceDashboard "HighTrafficSite" -RefreshSeconds 2
# Slower refresh for stable monitoring
Show-SitePerformanceDashboard "DocumentationSite" -RefreshSeconds 30
# Monitor during specific events
Show-SitePerformanceDashboard "LoadTestTarget" -RefreshSeconds 1
Real-World Examples:
Load Testing Dashboard:
# Set up dashboard for load testing
Write-Host "Load Test Dashboard Setup" -ForegroundColor Cyan
Write-Host "1. Start the dashboard"
Write-Host "2. Begin your load test"
Write-Host "3. Watch performance metrics in real-time"
Write-Host "4. Press Ctrl+C to stop monitoring"
Write-Host ""
# Start monitoring with aggressive refresh
Show-SitePerformanceDashboard "LoadTestSite" -RefreshSeconds 1
Production Monitoring:
# Production monitoring setup
function Start-ProductionMonitoring {
param([string]$SiteName)
Write-Host "Starting production monitoring for: $SiteName" -ForegroundColor Green
Write-Host "Dashboard will refresh every 10 seconds"
Write-Host "Watch for:"
Write-Host " - Memory usage > 500MB (Yellow) or > 1GB (Red)"
Write-Host " - CPU usage > 50% (Yellow) or > 80% (Red)"
Write-Host " - Response time > 1s (Yellow) or > 5s (Red)"
Write-Host " - Request queue > 0 (indicates bottleneck)"
Write-Host ""
Write-Host "Press Ctrl+C to stop monitoring"
Write-Host ""
Show-SitePerformanceDashboard $SiteName -RefreshSeconds 10
}
Start-ProductionMonitoring "EcommerceSite"
Troubleshooting Dashboard:
# Use during active troubleshooting
Write-Host "TROUBLESHOOTING MODE ACTIVATED" -ForegroundColor Red -BackgroundColor White
Write-Host "Monitoring: $siteName"
Write-Host "Reproduce the issue now..."
Write-Host "Watching for performance anomalies..."
# Aggressive monitoring during troubleshooting
Show-SitePerformanceDashboard "TroubleshootingSite" -RefreshSeconds 3
---
Basic Usage:
# Show recent log entries
Watch-IISLogs "MyWebsite"
# Output:
# Monitoring logs for: MyWebsite (Site ID: 1)
# Log path: C:\inetpub\logs\LogFiles\W3SVC1
# Errors only: False
# Follow mode: False
#
# Showing recent entries from: u_ex240711.log
# 2024-07-11 14:30:15 192.168.1.100 GET /home.aspx - 80 - 192.168.1.100 200 0 0 125
# 2024-07-11 14:30:16 192.168.1.101 GET /api/users - 80 - 192.168.1.101 200 0 0 89
Advanced Usage:
# Monitor only errors in real-time
Watch-IISLogs "MyWebsite" -ErrorsOnly -Follow
# Quick error review (recent errors only)
Watch-IISLogs "MyWebsite" -ErrorsOnly
# Follow logs in real-time (all requests)
Watch-IISLogs "MyWebsite" -Follow
Real-World Examples:
Deployment Monitoring:
# Monitor logs during deployment
Write-Host "Deployment Log Monitoring" -ForegroundColor Cyan
Write-Host "Monitoring for errors during deployment..."
Write-Host "Deploy your application now, watching for issues..."
Write-Host ""
# Watch for errors during deployment
Watch-IISLogs "DeploymentSite" -ErrorsOnly -Follow
# Use case: Run this in one PowerShell window while deploying in another
# Will show any 4xx/5xx errors that occur during deployment
Troubleshooting Session:
# Live troubleshooting
Write-Host "TROUBLESHOOTING SESSION STARTED" -ForegroundColor Yellow
Write-Host "Following logs in real-time..."
Write-Host "Reproduce the issue now to see what happens in the logs"
Write-Host ""
# Follow all requests during troubleshooting
Watch-IISLogs "ProblematicSite" -Follow
# In separate window, you can also monitor errors only:
# Watch-IISLogs "ProblematicSite" -ErrorsOnly -Follow
Security Monitoring:
# Monitor for security issues
Write-Host "Security Log Monitoring" -ForegroundColor Red
Write-Host "Watching for potential security issues..."
Write-Host "Looking for: 401 (auth failures), 403 (forbidden), 404 (scanning), etc."
Write-Host ""
# Monitor errors that might indicate security issues
Watch-IISLogs "PublicWebsite" -ErrorsOnly -Follow
# Look for patterns like:
# - Multiple 401s from same IP (brute force)
# - 404s for common attack vectors (/admin, /wp-admin, etc.)
# - 403s indicating access attempts to restricted areas
Performance Analysis:
# Monitor response patterns
function Analyze-ResponseTimes {
param([string]$SiteName)
Write-Host "Response Time Analysis for: $SiteName" -ForegroundColor Green
Write-Host "Following logs for 5 minutes to analyze response patterns..."
$startTime = Get-Date
$timeout = $startTime.AddMinutes(5)
# Start log monitoring in background job
$job = Start-Job -ScriptBlock {
param($site)
# Monitor logs and collect timing data
Watch-IISLogs $site -Follow
} -ArgumentList $SiteName
# Wait for timeout or manual stop
Write-Host "Monitoring... Press Ctrl+C to stop early or wait 5 minutes"
try {
while((Get-Date) -lt $timeout) {
Start-Sleep 10
Write-Host "Monitoring... $([math]::Round(($timeout - (Get-Date)).TotalMinutes,1)) minutes remaining"
}
} catch {
Write-Host "Monitoring stopped by user"
} finally {
Stop-Job $job
Remove-Job $job
}
Write-Host "Analysis complete. Review the log output above for patterns."
}
Analyze-ResponseTimes "AnalysisSite"
---
Basic Usage:
# Basic health check
Test-IISSiteHealth "MyWebsite"
# Output:
# Running health check for: MyWebsite
#
# === HEALTH CHECK RESULTS ===
# Site: MyWebsite
# Overall Health: Healthy
#
# CHECKS:
# Site Exists: ā Pass - Site found with ID 1
# Site State: ā Pass - Site is started
# App Pool State: ā Pass - MyAppPool is started
# Physical Path: ā Pass - Path exists: C:\inetpub\wwwroot\mysite
# Web.config: ā Pass - Configuration file is valid XML
# Site Bindings: ā Pass - 2 binding(s) configured
# HTTP Connectivity: ā Pass - HTTP 200 - OK
# SSL Certificate: ā Pass - Certificate valid for 87 days
# Worker Process Memory: ā Pass - 145MB memory usage
Advanced Usage:
# Comprehensive health check with performance metrics
Test-IISSiteHealth "MyWebsite" -IncludePerformance
# Store health check results for analysis
$healthResult = Test-IISSiteHealth "MyWebsite" -IncludePerformance
if($healthResult.OverallHealth -ne "Healthy") {
Write-Host "Site requires attention!" -ForegroundColor Red
# Take action based on results
}
Real-World Examples:
Daily Health Check Script:
# Daily health check for all production sites
function Invoke-DailyHealthCheck {
$reportDate = Get-Date -Format "yyyy-MM-dd"
$reportFile = "HealthReport_$reportDate.txt"
Write-Host "Daily Health Check - $reportDate" -ForegroundColor Green
"Daily Health Check - $reportDate" | Out-File $reportFile
"=" * 50 | Out-File $reportFile -Append
$productionSites = Get-IISSite | Where-Object {$_.Name -like "*prod*" -or $_.Name -like "*live*"}
$healthySites = 0
$warningSites = 0
$criticalSites = 0
foreach($site in $productionSites) {
Write-Host "Checking: $($site.Name)" -ForegroundColor Yellow
$health = Test-IISSiteHealth $site.Name -IncludePerformance
switch($health.OverallHealth) {
"Healthy" {
$healthySites++
Write-Host "ā $($site.Name) - Healthy" -ForegroundColor Green
}
"Warning" {
$warningSites++
Write-Host "ā $($site.Name) - Warning" -ForegroundColor Yellow
}
"Critical" {
$criticalSites++
Write-Host "ā $($site.Name) - Critical" -ForegroundColor Red
}
}
# Add to report
"`n=== $($site.Name) ===" | Out-File $reportFile -Append
"Overall Health: $($health.OverallHealth)" | Out-File $reportFile -Append
if($health.Errors.Count -gt 0) {
"ERRORS:" | Out-File $reportFile -Append
$health.Errors | ForEach-Object { " $_" | Out-File $reportFile -Append }
}
if($health.Warnings.Count -gt 0) {
"WARNINGS:" | Out-File $reportFile -Append
$health.Warnings | ForEach-Object { " $_" | Out-File $reportFile -Append }
}
}
# Summary
Write-Host "`nSUMMARY:" -ForegroundColor Cyan
Write-Host " Healthy: $healthySites" -ForegroundColor Green
Write-Host " Warning: $warningSites" -ForegroundColor Yellow
Write-Host " Critical: $criticalSites" -ForegroundColor Red
"`nSUMMARY:" | Out-File $reportFile -Append
" Healthy: $healthySites" | Out-File $reportFile -Append
" Warning: $warningSites" | Out-File $reportFile -Append
" Critical: $criticalSites" | Out-File $reportFile -Append
Write-Host "`nReport saved to: $reportFile" -ForegroundColor White
# Email report if there are issues
if($warningSites -gt 0 -or $criticalSites -gt 0) {
Write-Host "Issues detected - consider sending alert" -ForegroundColor Yellow
# Send-IISAlert -SiteName "Multiple Sites" -AlertType "Warning" -Message "Daily health check found $warningSites warnings and $criticalSites critical issues"
}
}
Invoke-DailyHealthCheck
Pre-Deployment Health Check:
# Pre-deployment validation
function Test-PreDeployment {
param([string[]]$SiteNames)
Write-Host "PRE-DEPLOYMENT HEALTH CHECK" -ForegroundColor Cyan
Write-Host "Validating environment before deployment..." -ForegroundColor White
$allHealthy = $true
foreach($siteName in $SiteNames) {
Write-Host "`nChecking: $siteName" -ForegroundColor Yellow
$health = Test-IISSiteHealth $siteName -IncludePerformance
if($health.OverallHealth -eq "Critical") {
Write-Host "DEPLOYMENT BLOCKED: $siteName has critical issues" -ForegroundColor Red -BackgroundColor White
Write-Host "Issues:" -ForegroundColor Red
$health.Errors | ForEach-Object { Write-Host " $_" -ForegroundColor Red }
$allHealthy = $false
} elseif($health.OverallHealth -eq "Warning") {
Write-Host "WARNING: $siteName has warnings (deployment can proceed)" -ForegroundColor Yellow
$health.Warnings | ForEach-Object { Write-Host " $_" -ForegroundColor Yellow }
} else {
Write-Host "ā $siteName ready for deployment" -ForegroundColor Green
}
}
if($allHealthy) {
Write-Host "`nā ALL SYSTEMS GO - DEPLOYMENT APPROVED" -ForegroundColor Green -BackgroundColor Black
return $true
} else {
Write-Host "`nā DEPLOYMENT BLOCKED - RESOLVE CRITICAL ISSUES FIRST" -ForegroundColor Red -BackgroundColor White
return $false
}
}
# Use before deployment
$deploymentSites = @("WebAPI", "UserPortal", "AdminPanel")
$canDeploy = Test-PreDeployment $deploymentSites
if($canDeploy) {
Write-Host "Proceeding with deployment..." -ForegroundColor Green
# Deployment script here
} else {
Write-Host "Deployment cancelled due to health check failures" -ForegroundColor Red
exit 1
}
Continuous Health Monitoring:
# Continuous health monitoring
function Start-ContinuousHealthMonitoring {
param(
[string[]]$SiteNames,
[int]$IntervalMinutes = 15
)
Write-Host "Starting continuous health monitoring" -ForegroundColor Green
Write-Host "Sites: $($SiteNames -join ', ')" -ForegroundColor White
Write-Host "Interval: $IntervalMinutes minutes" -ForegroundColor White
Write-Host "Press Ctrl+C to stop" -ForegroundColor Yellow
try {
while($true) {
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
Write-Host "`n[$timestamp] Health Check Cycle" -ForegroundColor Cyan
foreach($siteName in $SiteNames) {
$health = Test-IISSiteHealth $siteName
$color = switch($health.OverallHealth) {
"Healthy" { "Green" }
"Warning" { "Yellow" }
"Critical" { "Red" }
}
Write-Host " $siteName`: $($health.OverallHealth)" -ForegroundColor $color
# Alert on state changes or critical issues
if($health.OverallHealth -eq "Critical") {
Write-Host " CRITICAL ALERT: $siteName requires immediate attention" -ForegroundColor Red
# Send-IISAlert -SiteName $siteName -AlertType "Error" -Message "Critical health check failure"
}
}
Write-Host "Next check in $IntervalMinutes minutes..." -ForegroundColor Gray
Start-Sleep ($IntervalMinutes * 60)
}
} catch [System.Management.Automation.PipelineStoppedException] {
Write-Host "`nContinuous monitoring stopped" -ForegroundColor Yellow
}
}
# Monitor critical sites every 10 minutes
$criticalSites = @("PaymentGateway", "UserAuth", "MainAPI")
Start-ContinuousHealthMonitoring -SiteNames $criticalSites -IntervalMinutes 10
---
Basic Usage:
# Simple error alert
Send-IISAlert -SiteName "MyWebsite" -AlertType "Error" -Message "Site is down and not responding to HTTP requests"
# Warning alert
Send-IISAlert -SiteName "MyWebsite" -AlertType "Warning" -Message "High memory usage detected: 1.2GB"
# Info alert
Send-IISAlert -SiteName "MyWebsite" -AlertType "Info" -Message "Site successfully restarted after deployment"
Advanced Usage:
# Custom SMTP settings
Send-IISAlert -SiteName "CriticalSite" -AlertType "Error" -Message "Database connection failed" -SmtpServer "mail.company.com" -To @("admin@company.com", "oncall@company.com") -From "iis-alerts@company.com"
# Alert with detailed information
$alertMessage = @"
Site: MyWebsite
Issue: Application pool stopped unexpectedly
Time: $(Get-Date)
Worker Process: Not running
Last Error: $(Get-EventLog -LogName Application -Newest 1 | Where-Object {$_.Source -like "*IIS*"} | Select-Object -ExpandProperty Message)
Recovery Action Taken: Automatic restart attempted
Status: $(try { (Get-IISSite "MyWebsite").State } catch { "Unknown" })
"@
Send-IISAlert -SiteName "MyWebsite" -AlertType "Error" -Message $alertMessage
Real-World Examples:
Automated Alert System:
# Comprehensive alerting system
function Send-SmartAlert {
param(
[string]$SiteName,
[string]$IssueType,
[object]$HealthData = $null
)
$alertLevel = switch($IssueType) {
"SiteDown" { "Error" }
"HighMemory" { "Warning" }
"SlowResponse" { "Warning" }
"AppPoolStopped" { "Error" }
"SSLExpiring" { "Warning" }
"RecoverySuccess" { "Info" }
default { "Warning" }
}
# Build detailed message based on issue type
$message = switch($IssueType) {
"SiteDown" {
@"
CRITICAL: Site $SiteName is completely down
- Site State: $((Get-IISSite $SiteName -ea 0).State)
- App Pool State: $((Get-IISAppPool ((Get-IISSite $SiteName).Applications[0].ApplicationPoolName) -ea 0).State)
- HTTP Response: Failed
- Time: $(Get-Date)
Automatic recovery will be attempted.
If this alert persists, manual intervention is required.
"@
}
"HighMemory" {
$memUsage = if($HealthData) { $HealthData.MemoryMB } else { "Unknown" }
@"
WARNING: High memory usage detected for $SiteName
- Current Memory Usage: ${memUsage}MB
- Threshold: 1000MB
- Time: $(Get-Date)
Consider investigating for memory leaks or increasing app pool recycling frequency.
"@
}
"RecoverySuccess" {
@"
RECOVERY SUCCESS: $SiteName has been successfully restored
- Recovery Time: $(Get-Date)
- Site State: Started
- App Pool State: Started
- HTTP Response: OK
The site is now operational. Monitor for stability.
"@
}
default { "Issue detected with $SiteName`: $IssueType" }
}
Send-IISAlert -SiteName $SiteName -AlertType $alertLevel -Message $message
}
# Usage examples:
# Send-SmartAlert -SiteName "CriticalSite" -IssueType "SiteDown"
# Send-SmartAlert -SiteName "MemorySite" -IssueType "HighMemory" -HealthData @{MemoryMB=1200}
# Send-SmartAlert -SiteName "RecoveredSite" -IssueType "RecoverySuccess"
Alert Escalation System:
# Multi-level alert system
function Send-EscalatedAlert {
param(
[string]$SiteName,
[string]$Issue,
[int]$EscalationLevel = 1
)
$escalationConfig = @{
1 = @{ Recipients = @("l1-support@company.com"); Subject = "L1 Alert" }
2 = @{ Recipients = @("l1-support@company.com", "l2-support@company.com"); Subject = "L2 Escalation" }
3 = @{ Recipients = @("l1-support@company.com", "l2-support@company.com", "manager@company.com"); Subject = "L3 Critical Escalation" }
}
$config = $escalationConfig[$EscalationLevel]
$alertType = if($EscalationLevel -ge 3) { "Error" } else { "Warning" }
$message = @"
ESCALATION LEVEL $EscalationLevel
Site: $SiteName
Issue: $Issue
Time: $(Get-Date)
Server: $env:COMPUTERNAME
$(if($EscalationLevel -ge 3) { "IMMEDIATE ACTION REQUIRED - CRITICAL SYSTEM DOWN" } else { "Monitoring and resolution required" })
Please investigate and resolve immediately.
"@
Send-IISAlert -SiteName $SiteName -AlertType $alertType -Message $message -To $config.Recipients
Write-Host "Level $EscalationLevel alert sent for $SiteName" -ForegroundColor $(if($EscalationLevel -ge 3){"Red"}else{"Yellow"})
}
# Usage in monitoring:
# Send-EscalatedAlert -SiteName "CriticalSite" -Issue "Site unresponsive for 5 minutes" -EscalationLevel 1
# Start-Sleep 300 # Wait 5 minutes
# Send-EscalatedAlert -SiteName "CriticalSite" -Issue "Site still unresponsive after 10 minutes" -EscalationLevel 2
# Start-Sleep 600 # Wait 10 more minutes
# Send-EscalatedAlert -SiteName "CriticalSite" -Issue "Site down for 20 minutes - CRITICAL" -EscalationLevel 3
---
Basic Usage:
# Basic auto-recovery for critical sites
Start-IISAutoRecovery -SiteNames @("MainWebsite", "APIService")
# Output:
# Starting auto-recovery service for sites: MainWebsite, APIService
# Check interval: 60 seconds
# Max restart attempts: 3
# Press Ctrl+C to stop
#
# 2024-07-11 14:45:00 | MainWebsite passed health check
# 2024-07-11 14:45:00 | APIService passed health check
# (continues every 60 seconds...)
Advanced Usage:
# Aggressive monitoring for critical systems
Start-IISAutoRecovery -SiteNames @("PaymentGateway", "UserAuth") -CheckInterval 30 -MaxRestartAttempts 5
# Conservative monitoring for stable sites
Start-IISAutoRecovery -SiteNames @("Documentation", "Reports") -CheckInterval 300 -MaxRestartAttempts 2
# High-frequency monitoring during deployment
Start-IISAutoRecovery -SiteNames @("NewDeployment") -CheckInterval 15 -MaxRestartAttempts 1
Real-World Examples:
Production Auto-Recovery Setup:
# Production environment auto-recovery
function Start-ProductionAutoRecovery {
# STEP 1: REPLACE THESE WITH YOUR ACTUAL SITE NAMES
# To find your real site names, run: Get-IISSite | select Name
$criticalSites = @("[YOUR_PAYMENT_SITE]", "[YOUR_AUTH_SITE]", "[YOUR_MAIN_SITE]")
$importantSites = @("[YOUR_ADMIN_SITE]", "[YOUR_API_SITE]", "[YOUR_REPORTS_SITE]")
$standardSites = @("[YOUR_DOCS_SITE]", "[YOUR_SUPPORT_SITE]")
# EXAMPLE with real site names:
# $criticalSites = @("Default Web Site", "MyCompanyAPI", "UserPortal")
# $importantSites = @("AdminDashboard", "ReportsService")
# $standardSites = @("Documentation")
Write-Host "PRODUCTION AUTO-RECOVERY STARTING" -ForegroundColor Green -BackgroundColor Black
Write-Host "Critical Sites: $($criticalSites -join ', ')" -ForegroundColor Red
Write-Host "Important Sites: $($importantSites -join ', ')" -ForegroundColor Yellow
Write-Host "Standard Sites: $($standardSites -join ', ')" -ForegroundColor White
# Start separate monitoring for each group
Write-Host "`nStarting monitoring services..." -ForegroundColor Cyan
# Critical - aggressive monitoring
Start-Job -Name "CriticalMonitoring" -ScriptBlock {
param($sites)
Import-Module WebAdministration,IISAdministration
# Import your custom functions here
Start-IISAutoRecovery -SiteNames $sites -CheckInterval 30 -MaxRestartAttempts 5
} -ArgumentList $criticalSites
# Important - moderate monitoring
Start-Job -Name "ImportantMonitoring" -ScriptBlock {
param($sites)
Import-Module WebAdministration,IISAdministration
Start-IISAutoRecovery -SiteNames $sites -CheckInterval 60 -MaxRestartAttempts 3
} -ArgumentList $importantSites
# Standard - basic monitoring
Start-Job -Name "StandardMonitoring" -ScriptBlock {
param($sites)
Import-Module WebAdministration,IISAdministration
Start-IISAutoRecovery -SiteNames $sites -CheckInterval 300 -MaxRestartAttempts 2
} -ArgumentList $standardSites
Write-Host "All monitoring services started in background jobs" -ForegroundColor Green
Write-Host "Use 'Get-Job' to check status, 'Stop-Job' to stop monitoring" -ForegroundColor White
}
Start-ProductionAutoRecovery
Deployment Auto-Recovery:
# Auto-recovery during deployment window
function Start-DeploymentMonitoring {
param([string[]]$SiteNames, [int]$DeploymentWindowMinutes = 60)
Write-Host "DEPLOYMENT MONITORING ACTIVATED" -ForegroundColor Cyan -BackgroundColor Black
Write-Host "Sites: $($SiteNames -join ', ')" -ForegroundColor White
Write-Host "Window: $DeploymentWindowMinutes minutes" -ForegroundColor White
Write-Host "Aggressive monitoring during deployment..." -ForegroundColor Yellow
$endTime = (Get-Date).AddMinutes($DeploymentWindowMinutes)
# Start auto-recovery with deployment-specific settings
$job = Start-Job -ScriptBlock {
param($sites, $endTime)
Import-Module WebAdministration,IISAdministration
# Aggressive monitoring during deployment
try {
Start-IISAutoRecovery -SiteNames $sites -CheckInterval 15 -MaxRestartAttempts 1
} catch [System.Management.Automation.PipelineStoppedException] {
Write-Host "Deployment monitoring stopped"
}
} -ArgumentList $SiteNames, $endTime
# Monitor the monitoring job
try {
while((Get-Date) -lt $endTime -and $job.State -eq "Running") {
$remaining = [math]::Round(($endTime - (Get-Date)).TotalMinutes, 1)
Write-Host "Deployment monitoring active - $remaining minutes remaining" -ForegroundColor Green
Start-Sleep 60
}
} catch {
Write-Host "Deployment monitoring interrupted" -ForegroundColor Yellow
} finally {
Stop-Job $job -ErrorAction SilentlyContinue
Remove-Job $job -ErrorAction SilentlyContinue
Write-Host "Deployment monitoring window closed" -ForegroundColor Cyan
}
}
# Use during deployment
$deploymentSites = @("WebAPI", "UserPortal", "AdminDashboard")
Start-DeploymentMonitoring -SiteNames $deploymentSites -DeploymentWindowMinutes 45
24/7 Monitoring Service:
# Enterprise 24/7 monitoring setup
function Install-IISMonitoringService {
$serviceScript = @'
# IIS Monitoring Service Script
Import-Module WebAdministration,IISAdministration
# Load custom functions (you'd import your module here)
# Import-Module IISUtilities
$criticalSites = @("MainWebsite", "PaymentAPI", "UserAuth")
$logFile = "C:\Logs\IISMonitoring.log"
function Write-MonitoringLog {
param([string]$Message, [string]$Level = "INFO")
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
"$timestamp [$Level] $Message" | Out-File $logFile -Append
}
Write-MonitoringLog "IIS Monitoring Service Starting" "INFO"
try {
Start-IISAutoRecovery -SiteNames $criticalSites -CheckInterval 60 -MaxRestartAttempts 3
} catch {
Write-MonitoringLog "Monitoring service error: $($_.Exception.Message)" "ERROR"
} finally {
Write-MonitoringLog "IIS Monitoring Service Stopped" "INFO"
}
'@
# Save monitoring script
$scriptPath = "C:\Scripts\IISMonitoring.ps1"
$serviceScript | Out-File $scriptPath -Encoding UTF8
# Create Windows service (requires NSSM or similar)
Write-Host "Monitoring script created at: $scriptPath" -ForegroundColor Green
Write-Host "To install as Windows service:" -ForegroundColor Yellow
Write-Host "1. Install NSSM (Non-Sucking Service Manager)" -ForegroundColor White
Write-Host "2. Run: nssm install IISMonitoring powershell.exe" -ForegroundColor White
Write-Host "3. Set arguments: -ExecutionPolicy Bypass -File `"$scriptPath`"" -ForegroundColor White
Write-Host "4. Configure service recovery options" -ForegroundColor White
}
Install-IISMonitoringService
---
Basic Usage:
# Check status of all sites
Invoke-BulkSiteOperation -SitePattern "*" -Operation "Status"
# Output:
# Found 5 sites matching pattern: *
# - MainWebsite
# - TestSite
# - DevPortal
# - APIService
# - Documentation
#
# Proceed with Status operation on these sites? (y/N): y
#
# Executing Status operation...
#
# RESULTS:
# Site Operation Status Message
# ---- --------- ------ -------
# MainWebsite Status Info Site: Started, Pool: Started
# TestSite Status Info Site: Stopped, Pool: Stopped
# DevPortal Status Info Site: Started, Pool: Started
Advanced Usage:
# Restart all test sites in parallel
Invoke-BulkSiteOperation -SitePattern "*test*" -Operation "Restart" -Parallel
# Health check all production sites
Invoke-BulkSiteOperation -SitePattern "*prod*" -Operation "HealthCheck"
# Start all stopped sites
Invoke-BulkSiteOperation -SitePattern "*" -Operation "Start"
# Stop development sites for maintenance
Invoke-BulkSiteOperation -SitePattern "*dev*" -Operation "Stop"
Real-World Examples:
Environment Management:
# Development environment reset
function Reset-DevelopmentEnvironment {
Write-Host "DEVELOPMENT ENVIRONMENT RESET" -ForegroundColor Cyan
Write-Host "This will restart all development and test sites" -ForegroundColor Yellow
# Stop all dev/test sites
Write-Host "`n1. Stopping all development sites..." -ForegroundColor Yellow
Invoke-BulkSiteOperation -SitePattern "*dev*" -Operation "Stop"
Write-Host "`n2. Stopping all test sites..." -ForegroundColor Yellow
Invoke-BulkSiteOperation -SitePattern "*test*" -Operation "Stop"
# Clear temp files, logs, etc. here
Write-Host "`n3. Clearing temporary files..." -ForegroundColor Yellow
# Add cleanup logic
# Restart everything
Write-Host "`n4. Starting all development sites..." -ForegroundColor Green
Invoke-BulkSiteOperation -SitePattern "*dev*" -Operation "Start"
Write-Host "`n5. Starting all test sites..." -ForegroundColor Green
Invoke-BulkSiteOperation -SitePattern "*test*" -Operation "Start"
Write-Host "`nDevelopment environment reset complete!" -ForegroundColor Green
}
Reset-DevelopmentEnvironment
Maintenance Window Operations:
# Scheduled maintenance operations
function Invoke-MaintenanceWindow {
param([string]$Environment = "prod")
$maintenanceStart = Get-Date
Write-Host "MAINTENANCE WINDOW STARTED" -ForegroundColor Red -BackgroundColor White
Write-Host "Environment: $Environment" -ForegroundColor White
Write-Host "Start Time: $maintenanceStart" -ForegroundColor White
try {
# 1. Health check before maintenance
Write-Host "`n=== PRE-MAINTENANCE HEALTH CHECK ===" -ForegroundColor Cyan
$preResults = Invoke-BulkSiteOperation -SitePattern "*$Environment*" -Operation "HealthCheck"
# 2. Stop sites gracefully
Write-Host "`n=== STOPPING SITES ===" -ForegroundColor Yellow
Invoke-BulkSiteOperation -SitePattern "*$Environment*" -Operation "Stop"
# 3. Perform maintenance tasks
Write-Host "`n=== MAINTENANCE TASKS ===" -ForegroundColor Yellow
Write-Host "Performing maintenance tasks..." -ForegroundColor White
# Example maintenance tasks:
# - Clear temporary files
# - Update configurations
# - Apply patches
# - Database maintenance
# - Log cleanup
Start-Sleep 30 # Simulate maintenance work
# 4. Restart sites
Write-Host "`n=== RESTARTING SITES ===" -ForegroundColor Green
$restartResults = Invoke-BulkSiteOperation -SitePattern "*$Environment*" -Operation "Restart" -Parallel
# 5. Post-maintenance health check
Write-Host "`n=== POST-MAINTENANCE HEALTH CHECK ===" -ForegroundColor Cyan
Start-Sleep 30 # Allow time for sites to fully start
$postResults = Invoke-BulkSiteOperation -SitePattern "*$Environment*" -Operation "HealthCheck"
$maintenanceEnd = Get-Date
$duration = $maintenanceEnd - $maintenanceStart
Write-Host "`nMAINTENANCE WINDOW COMPLETED" -ForegroundColor Green -BackgroundColor Black
Write-Host "Duration: $($duration.TotalMinutes.ToString('F1')) minutes" -ForegroundColor White
} catch {
Write-Host "`nMAINTENANCE WINDOW ERROR: $($_.Exception.Message)" -ForegroundColor Red
Write-Host "Attempting emergency recovery..." -ForegroundColor Yellow
# Emergency recovery
Invoke-BulkSiteOperation -SitePattern "*$Environment*" -Operation "Start"
}
}
# Scheduled maintenance for production
Invoke-MaintenanceWindow -Environment "prod"
Disaster Recovery:
# Disaster recovery operations
function Invoke-DisasterRecovery {
param([string]$Scope = "all")
Write-Host "DISASTER RECOVERY INITIATED" -ForegroundColor Red -BackgroundColor White
Write-Host "Scope: $Scope" -ForegroundColor White
Write-Host "Time: $(Get-Date)" -ForegroundColor White
$recoveryLog = "DisasterRecovery_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
"Disaster Recovery Log - $(Get-Date)" | Out-File $recoveryLog
try {
# 1. Assess current state
Write-Host "`n=== ASSESSING CURRENT STATE ===" -ForegroundColor Cyan
"=== INITIAL STATE ASSESSMENT ===" | Out-File $recoveryLog -Append
$currentState = Invoke-BulkSiteOperation -SitePattern "*$Scope*" -Operation "Status"
$currentState | Out-String | Out-File $recoveryLog -Append
$failedSites = $currentState | Where-Object {$_.Status -eq "Error"}
Write-Host "Sites requiring recovery: $($failedSites.Count)" -ForegroundColor Red
# 2. Attempt automatic recovery
if($failedSites.Count -gt 0) {
Write-Host "`n=== AUTOMATIC RECOVERY ATTEMPT ===" -ForegroundColor Yellow
"=== AUTOMATIC RECOVERY ATTEMPT ===" | Out-File $recoveryLog -Append
foreach($site in $failedSites) {
Write-Host "Recovering: $($site.Site)" -ForegroundColor Yellow
try {
$success = Invoke-SiteRecovery $site.Site
if($success) {
Write-Host "ā $($site.Site) recovered" -ForegroundColor Green
"SUCCESS: $($site.Site) recovered" | Out-File $recoveryLog -Append
} else {
Write-Host "ā $($site.Site) recovery failed" -ForegroundColor Red
"FAILED: $($site.Site) recovery failed" | Out-File $recoveryLog -Append
}
} catch {
Write-Host "ā $($site.Site) recovery error: $($_.Exception.Message)" -ForegroundColor Red
"ERROR: $($site.Site) - $($_.Exception.Message)" | Out-File $recoveryLog -Append
}
}
}
# 3. Final state assessment
Write-Host "`n=== FINAL STATE ASSESSMENT ===" -ForegroundColor Cyan
"=== FINAL STATE ASSESSMENT ===" | Out-File $recoveryLog -Append
$finalState = Invoke-BulkSiteOperation -SitePattern "*$Scope*" -Operation "HealthCheck"
$finalState | Out-String | Out-File $recoveryLog -Append
$stillFailed = $finalState | Where-Object {$_.Status -eq "Error"}
if($stillFailed.Count -eq 0) {
Write-Host "ā ALL SITES RECOVERED SUCCESSFULLY" -ForegroundColor Green -BackgroundColor Black
"DISASTER RECOVERY SUCCESSFUL - ALL SITES OPERATIONAL" | Out-File $recoveryLog -Append
} else {
Write-Host "ā $($stillFailed.Count) SITES STILL REQUIRE MANUAL INTERVENTION" -ForegroundColor Red -BackgroundColor White
Write-Host "Failed sites:" -ForegroundColor Red
$stillFailed | ForEach-Object { Write-Host " - $($_.Site)" -ForegroundColor Red }
"MANUAL INTERVENTION REQUIRED FOR:" | Out-File $recoveryLog -Append
$stillFailed | ForEach-Object { " - $($_.Site)" | Out-File $recoveryLog -Append }
}
} catch {
Write-Host "DISASTER RECOVERY ERROR: $($_.Exception.Message)" -ForegroundColor Red
"DISASTER RECOVERY ERROR: $($_.Exception.Message)" | Out-File $recoveryLog -Append
} finally {
Write-Host "`nRecovery log saved to: $recoveryLog" -ForegroundColor White
}
}
# Use during major outage
Invoke-DisasterRecovery -Scope "prod"
---
# Complete monitoring solution setup
function Deploy-ComprehensiveMonitoring {
Write-Host "DEPLOYING COMPREHENSIVE IIS MONITORING" -ForegroundColor Green -BackgroundColor Black
# 1. Identify site categories
$sites = Get-IISSite
$criticalSites = $sites | Where-Object {$_.Name -like "*prod*" -or $_.Name -like "*payment*" -or $_.Name -like "*auth*"}
$importantSites = $sites | Where-Object {$_.Name -like "*api*" -or $_.Name -like "*service*"}
$standardSites = $sites | Where-Object {$_.Name -notlike "*prod*" -and $_.Name -notlike "*payment*" -and $_.Name -notlike "*auth*" -and $_.Name -notlike "*api*" -and $_.Name -notlike "*service*"}
Write-Host "`nSite Categories:" -ForegroundColor Cyan
Write-Host "Critical ($($criticalSites.Count)): $($criticalSites.Name -join ', ')" -ForegroundColor Red
Write-Host "Important ($($importantSites.Count)): $($importantSites.Name -join ', ')" -ForegroundColor Yellow
Write-Host "Standard ($($standardSites.Count)): $($standardSites.Name -join ', ')" -ForegroundColor White
# 2. Initial health check
Write-Host "`n=== INITIAL HEALTH ASSESSMENT ===" -ForegroundColor Cyan
foreach($site in $sites) {
$health = Test-IISSiteHealth $site.Name
$color = switch($health.OverallHealth) { "Healthy"{"Green"} "Warning"{"Yellow"} "Critical"{"Red"} }
Write-Host "$($site.Name): $($health.OverallHealth)" -ForegroundColor $color
}
# 3. Start monitoring services
Write-Host "`n=== STARTING MONITORING SERVICES ===" -ForegroundColor Green
if($criticalSites.Count -gt 0) {
Write-Host "Starting critical site monitoring (30s intervals)..." -ForegroundColor Red
Start-Job -Name "CriticalMonitoring" -ScriptBlock {
param($sites)
Import-Module WebAdministration,IISAdministration
Start-IISAutoRecovery -SiteNames $sites -CheckInterval 30 -MaxRestartAttempts 5
} -ArgumentList $criticalSites.Name
}
if($importantSites.Count -gt 0) {
Write-Host "Starting important site monitoring (60s intervals)..." -ForegroundColor Yellow
Start-Job -Name "ImportantMonitoring" -ScriptBlock {
param($sites)
Import-Module WebAdministration,IISAdministration
Start-IISAutoRecovery -SiteNames $sites -CheckInterval 60 -MaxRestartAttempts 3
} -ArgumentList $importantSites.Name
}
if($standardSites.Count -gt 0) {
Write-Host "Starting standard site monitoring (300s intervals)..." -ForegroundColor White
Start-Job -Name "StandardMonitoring" -ScriptBlock {
param($sites)
Import-Module WebAdministration,IISAdministration
Start-IISAutoRecovery -SiteNames $sites -CheckInterval 300 -MaxRestartAttempts 2
} -ArgumentList $standardSites.Name
}
# 4. Show monitoring status
Write-Host "`n=== MONITORING STATUS ===" -ForegroundColor Green
Get-Job | Where-Object {$_.Name -like "*Monitoring"} | Format-Table Name, State -AutoSize
Write-Host "`nMonitoring deployed successfully!" -ForegroundColor Green
Write-Host "Use 'Get-Job' to check status" -ForegroundColor White
Write-Host "Use 'Stop-Job -Name JobName' to stop specific monitoring" -ForegroundColor White
Write-Host "Use 'Get-Job | Stop-Job' to stop all monitoring" -ForegroundColor White
}
Deploy-ComprehensiveMonitoring
# Complete deployment pipeline with monitoring
function Invoke-DeploymentPipeline {
param(
[string[]]$SiteNames,
[string]$DeploymentPackage,
[int]$MonitoringMinutes = 30
)
$deploymentStart = Get-Date
Write-Host "DEPLOYMENT PIPELINE STARTED" -ForegroundColor Cyan -BackgroundColor Black
Write-Host "Sites: $($SiteNames -join ', ')" -ForegroundColor White
Write-Host "Package: $DeploymentPackage" -ForegroundColor White
Write-Host "Start Time: $deploymentStart" -ForegroundColor White
try {
# 1. Pre-deployment health check
Write-Host "`n=== PRE-DEPLOYMENT HEALTH CHECK ===" -ForegroundColor Cyan
$preDeployHealth = @{}
foreach($site in $SiteNames) {
$health = Test-IISSiteHealth $site -IncludePerformance
$preDeployHealth[$site] = $health
if($health.OverallHealth -eq "Critical") {
throw "Pre-deployment check failed: $site has critical issues"
} elseif($health.OverallHealth -eq "Warning") {
Write-Host "WARNING: $site has warnings but deployment can proceed" -ForegroundColor Yellow
} else {
Write-Host "ā $site ready for deployment" -ForegroundColor Green
}
}
# 2. Start deployment monitoring
Write-Host "`n=== STARTING DEPLOYMENT MONITORING ===" -ForegroundColor Yellow
$monitoringJob = Start-Job -ScriptBlock {
param($sites, $minutes)
Import-Module WebAdministration,IISAdministration
Start-IISAutoRecovery -SiteNames $sites -CheckInterval 15 -MaxRestartAttempts 2
} -ArgumentList $SiteNames, $MonitoringMinutes
# 3. Deploy application
Write-Host "`n=== DEPLOYING APPLICATION ===" -ForegroundColor Green
foreach($site in $SiteNames) {
Write-Host "Deploying to: $site" -ForegroundColor Yellow
# Stop site
Stop-IISSite $site
Write-Host " Site stopped" -ForegroundColor White
# Deploy files (simulate deployment)
Write-Host " Deploying files..." -ForegroundColor White
Start-Sleep 5 # Simulate deployment time
# Start site
Start-IISSite $site
Write-Host " Site started" -ForegroundColor Green
# Wait for site to be ready
Start-Sleep 10
}
# 4. Post-deployment verification
Write-Host "`n=== POST-DEPLOYMENT VERIFICATION ===" -ForegroundColor Cyan
$allHealthy = $true
foreach($site in $SiteNames) {
Write-Host "Verifying: $site" -ForegroundColor Yellow
# Health check
$postHealth = Test-IISSiteHealth $site -IncludePerformance
if($postHealth.OverallHealth -ne "Healthy") {
Write-Host "ā $site verification failed: $($postHealth.OverallHealth)" -ForegroundColor Red
$allHealthy = $false
} else {
Write-Host "ā $site verification passed" -ForegroundColor Green
}
}
# 5. Generate deployment report
$deploymentEnd = Get-Date
$duration = $deploymentEnd - $deploymentStart
Write-Host "`n=== DEPLOYMENT SUMMARY ===" -ForegroundColor Cyan
Write-Host "Status: $(if($allHealthy){'SUCCESS'}else{'FAILED'})" -ForegroundColor $(if($allHealthy){'Green'}else{'Red'})
Write-Host "Duration: $($duration.TotalMinutes.ToString('F1')) minutes" -ForegroundColor White
Write-Host "Sites: $($SiteNames -join ', ')" -ForegroundColor White
if($allHealthy) {
Write-Host "ā DEPLOYMENT COMPLETED SUCCESSFULLY" -ForegroundColor Green -BackgroundColor Black
} else {
Write-Host "ā DEPLOYMENT VERIFICATION FAILED" -ForegroundColor Red -BackgroundColor White
throw "Deployment verification failed"
}
} catch {
Write-Host "`nDEPLOYMENT ERROR: $($_.Exception.Message)" -ForegroundColor Red
# Rollback attempt
Write-Host "Attempting automatic rollback..." -ForegroundColor Yellow
foreach($site in $SiteNames) {
try {
Invoke-SiteRecovery $site
Write-Host "ā $site recovery attempted" -ForegroundColor Yellow
} catch {
Write-Host "ā $site recovery failed" -ForegroundColor Red
}
}
throw "Deployment failed and rollback attempted"
} finally {
# Stop monitoring
if($monitoringJob) {
Stop-Job $monitoringJob -ErrorAction SilentlyContinue
Remove-Job $monitoringJob -ErrorAction SilentlyContinue
}
Write-Host "`nDeployment monitoring stopped" -ForegroundColor Gray
}
}
# USAGE EXAMPLES:
# Simple deployment
# REPLACE WITH YOUR REAL SITE NAMES:
Invoke-DeploymentPipeline -SiteNames @("[YOUR_SITE1]", "[YOUR_SITE2]") -DeploymentPackage "v2.1.0"
# REAL EXAMPLE:
Invoke-DeploymentPipeline -SiteNames @("Default Web Site", "MyAPI") -DeploymentPackage "v2.1.0"
# Extended monitoring during deployment
Invoke-DeploymentPipeline -SiteNames @("CriticalSite") -DeploymentPackage "v2.1.0" -MonitoringMinutes 60
# Complete emergency response workflow
function Invoke-EmergencyResponse {
param(
[string]$IncidentType,
[string[]]$AffectedSites = @(),
[string]$Severity = "High"
)
$incidentStart = Get-Date
$incidentId = "INC-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
Write-Host "šØ EMERGENCY RESPONSE ACTIVATED šØ" -ForegroundColor Red -BackgroundColor White
Write-Host "Incident ID: $incidentId" -ForegroundColor White
Write-Host "Type: $IncidentType" -ForegroundColor White
Write-Host "Severity: $Severity" -ForegroundColor White
Write-Host "Start Time: $incidentStart" -ForegroundColor White
$logFile = "Emergency_$incidentId.log"
"Emergency Response Log - $incidentId" | Out-File $logFile
"Incident Type: $IncidentType" | Out-File $logFile -Append
"Severity: $Severity" | Out-File $logFile -Append
"Start Time: $incidentStart" | Out-File $logFile -Append
try {
# 1. Immediate assessment
Write-Host "`n=== IMMEDIATE ASSESSMENT ===" -ForegroundColor Red
"=== IMMEDIATE ASSESSMENT ===" | Out-File $logFile -Append
if($AffectedSites.Count -eq 0) {
# Auto-detect affected sites
Write-Host "Auto-detecting affected sites..." -ForegroundColor Yellow
$allSites = Get-IISSite
$AffectedSites = @()
foreach($site in $allSites) {
try {
$response = Invoke-WebRequest "http://localhost" -UseBasicParsing -TimeoutSec 5
if($response.StatusCode -ne 200) {
$AffectedSites += $site.Name
}
} catch {
$AffectedSites += $site.Name
}
}
}
Write-Host "Affected sites: $($AffectedSites.Count)" -ForegroundColor Red
$AffectedSites | ForEach-Object {
Write-Host " - $_" -ForegroundColor Red
"AFFECTED: $_" | Out-File $logFile -Append
}
# 2. Emergency recovery
Write-Host "`n=== EMERGENCY RECOVERY ===" -ForegroundColor Yellow
"=== EMERGENCY RECOVERY ===" | Out-File $logFile -Append
$recoveredSites = @()
$failedSites = @()
foreach($site in $AffectedSites) {
Write-Host "Emergency recovery: $site" -ForegroundColor Yellow
try {
$success = Invoke-SiteRecovery $site
if($success) {
$recoveredSites += $site
Write-Host "ā $site recovered" -ForegroundColor Green
"RECOVERED: $site" | Out-File $logFile -Append
} else {
$failedSites += $site
Write-Host "ā $site recovery failed" -ForegroundColor Red
"FAILED RECOVERY: $site" | Out-File $logFile -Append
}
} catch {
$failedSites += $site
Write-Host "ā $site recovery error: $($_.Exception.Message)" -ForegroundColor Red
"ERROR: $site - $($_.Exception.Message)" | Out-File $logFile -Append
}
}
# 3. Service restoration verification
Write-Host "`n=== SERVICE RESTORATION VERIFICATION ===" -ForegroundColor Cyan
"=== SERVICE RESTORATION VERIFICATION ===" | Out-File $logFile -Append
Start-Sleep 30 # Allow time for services to stabilize
$finalStatus = @()
foreach($site in $AffectedSites) {
$health = Test-IISSiteHealth $site
$finalStatus += [PSCustomObject]@{
Site = $site
Status = $health.OverallHealth
Recovered = $recoveredSites -contains $site
}
}
# 4. Incident summary
Write-Host "`n=== INCIDENT SUMMARY ===" -ForegroundColor Cyan
"=== INCIDENT SUMMARY ===" | Out-File $logFile -Append
$incidentEnd = Get-Date
$duration = $incidentEnd - $incidentStart
$fullyRecovered = ($finalStatus | Where-Object {$_.Status -eq "Healthy"}).Count
$totalAffected = $AffectedSites.Count
Write-Host "Incident Duration: $($duration.TotalMinutes.ToString('F1')) minutes" -ForegroundColor White
Write-Host "Sites Affected: $totalAffected" -ForegroundColor White
Write-Host "Sites Recovered: $fullyRecovered" -ForegroundColor Green
Write-Host "Sites Still Down: $($totalAffected - $fullyRecovered)" -ForegroundColor Red
"Duration: $($duration.TotalMinutes.ToString('F1')) minutes" | Out-File $logFile -Append
"Sites Affected: $totalAffected" | Out-File $logFile -Append
"Sites Recovered: $fullyRecovered" | Out-File $logFile -Append
"Sites Still Down: $($totalAffected - $fullyRecovered)" | Out-File $logFile -Append
if($fullyRecovered -eq $totalAffected) {
Write-Host "`nā
ALL SERVICES RESTORED" -ForegroundColor Green -BackgroundColor Black
"INCIDENT RESOLVED - ALL SERVICES RESTORED" | Out-File $logFile -Append
} else {
Write-Host "`nā ļø PARTIAL RECOVERY - ESCALATION REQUIRED" -ForegroundColor Red -BackgroundColor White
"PARTIAL RECOVERY - MANUAL INTERVENTION REQUIRED" | Out-File $logFile -Append
Write-Host "`nSites requiring manual intervention:" -ForegroundColor Red
$finalStatus | Where-Object {$_.Status -ne "Healthy"} | ForEach-Object {
Write-Host " - $($_.Site): $($_.Status)" -ForegroundColor Red
"MANUAL REQUIRED: $($_.Site) - $($_.Status)" | Out-File $logFile -Append
}
}
} catch {
Write-Host "`nEMERGENCY RESPONSE ERROR: $($_.Exception.Message)" -ForegroundColor Red
"EMERGENCY RESPONSE ERROR: $($_.Exception.Message)" | Out-File $logFile -Append
} finally {
Write-Host "`nEmergency response log: $logFile" -ForegroundColor White
Write-Host "Incident ID: $incidentId" -ForegroundColor White
}
}
# USAGE EXAMPLES:
# Auto-detect and recover all down sites
Invoke-EmergencyResponse -IncidentType "Mass Site Outage" -Severity "Critical"
# Target specific sites
# REPLACE WITH YOUR REAL SITE NAMES:
Invoke-EmergencyResponse -IncidentType "Payment System Down" -AffectedSites @("[YOUR_PAYMENT_SITE]", "[YOUR_AUTH_SITE]") -Severity "Critical"
# REAL EXAMPLE:
Invoke-EmergencyResponse -IncidentType "Main Sites Down" -AffectedSites @("Default Web Site", "MyAPI") -Severity "High"
# Complete daily operations checklist
function Invoke-DailyOperations {
param([string]$Environment = "production")
$dailyStart = Get-Date
$reportDate = Get-Date -Format "yyyy-MM-dd"
$reportFile = "DailyOps_$reportDate.html"
Write-Host "š DAILY OPERATIONS CHECKLIST - $reportDate" -ForegroundColor Cyan -BackgroundColor Black
$htmlReport = @"
<!DOCTYPE html>
<html>
<head>
<title>Daily Operations Report - $reportDate</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.header { background-color: #2c3e50; color: white; padding: 20px; text-align: center; }
.section { margin: 20px 0; padding: 15px; border-left: 4px solid #3498db; }
.healthy { color: green; font-weight: bold; }
.warning { color: orange; font-weight: bold; }
.critical { color: red; font-weight: bold; }
table { width: 100%; border-collapse: collapse; margin: 10px 0; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
</style>
</head>
<body>
<div class="header">
<h1>Daily Operations Report</h1>
<h2>$reportDate - $env:COMPUTERNAME</h2>
</div>
"@
try {
# 1. System Health Check
Write-Host "`n=== SYSTEM HEALTH CHECK ===" -ForegroundColor Green
$htmlReport += "<div class='section'><h2>System Health Check</h2>"
# IIS Services
$services = Get-Service W3SVC, WAS, IISADMIN
$htmlReport += "<h3>IIS Services</h3><table><tr><th>Service</th><th>Status</th></tr>"
foreach($service in $services) {
$status = $service.Status
$statusClass = if($status -eq "Running") {"healthy"} else {"critical"}
Write-Host "$($service.Name): $status" -ForegroundColor $(if($status -eq "Running"){"Green"}else{"Red"})
$htmlReport += "<tr><td>$($service.Name)</td><td class='$statusClass'>$status</td></tr>"
}
$htmlReport += "</table>"
# 2. Site Health Assessment
Write-Host "`n=== SITE HEALTH ASSESSMENT ===" -ForegroundColor Green
$htmlReport += "<h3>Site Health Assessment</h3><table><tr><th>Site</th><th>State</th><th>App Pool</th><th>Health</th><th>Response</th></tr>"
$sites = Get-IISSite | Where-Object {$_.Name -like "*$Environment*" -or $Environment -eq "all"}
$healthySites = 0
$warningSites = 0
$criticalSites = 0
foreach($site in $sites) {
Write-Host "Checking: $($site.Name)" -ForegroundColor Yellow
$health = Test-IISSiteHealth $site.Name
$appPool = (Get-IISAppPool $site.Applications[0].ApplicationPoolName).State
# Test HTTP response
$httpStatus = "Unknown"
try {
$binding = Get-IISSiteBinding $site.Name | Where-Object {$_.Protocol -eq "http"} | Select-Object -First 1
if($binding) {
$testUrl = "http://localhost$($binding.BindingInformation.Split(':')[1])"
$response = Invoke-WebRequest $testUrl -UseBasicParsing -TimeoutSec 5
$httpStatus = $response.StatusCode
}
} catch {
$httpStatus = "Failed"
}
$healthClass = switch($health.OverallHealth) {
"Healthy" { $healthySites++; "healthy" }
"Warning" { $warningSites++; "warning" }
"Critical" { $criticalSites++; "critical" }
}
Write-Host " $($site.Name): $($health.OverallHealth)" -ForegroundColor $(switch($health.OverallHealth) {"Healthy"{"Green"} "Warning"{"Yellow"} "Critical"{"Red"}})
$htmlReport += "<tr><td>$($site.Name)</td><td>$($site.State)</td><td>$appPool</td><td class='$healthClass'>$($health.OverallHealth)</td><td>$httpStatus</td></tr>"
}
$htmlReport += "</table>"
# 3. Performance Summary
Write-Host "`n=== PERFORMANCE SUMMARY ===" -ForegroundColor Green
$htmlReport += "<h3>Performance Summary</h3><table><tr><th>Metric</th><th>Value</th></tr>"
# Memory usage
$totalMemory = (Get-Process w3wp -ErrorAction SilentlyContinue | Measure-Object -Property WorkingSet -Sum).Sum / 1GB
Write-Host "Total IIS Memory Usage: $([math]::Round($totalMemory, 2))GB" -ForegroundColor White
$htmlReport += "<tr><td>Total IIS Memory Usage</td><td>$([math]::Round($totalMemory, 2))GB</td></tr>"
# Active connections
try {
$connections = (Get-Counter "\Web Service(_Total)\Current Connections" -SampleInterval 1 -MaxSamples 1).CounterSamples[0].CookedValue
Write-Host "Total Active Connections: $connections" -ForegroundColor White
$htmlReport += "<tr><td>Total Active Connections</td><td>$connections</td></tr>"
} catch {
Write-Host "Total Active Connections: Unable to retrieve" -ForegroundColor Gray
$htmlReport += "<tr><td>Total Active Connections</td><td>Unable to retrieve</td></tr>"
}
# Worker processes
$workerProcesses = (Get-Process w3wp -ErrorAction SilentlyContinue).Count
Write-Host "Active Worker Processes: $workerProcesses" -ForegroundColor White
$htmlReport += "<tr><td>Active Worker Processes</td><td>$workerProcesses</td></tr>"
$htmlReport += "</table>"
# 4. Disk Space Check
Write-Host "`n=== DISK SPACE CHECK ===" -ForegroundColor Green
$htmlReport += "<h3>Disk Space Check</h3><table><tr><th>Drive</th><th>Total (GB)</th><th>Free (GB)</th><th>Free %</th><th>Status</th></tr>"
$drives = Get-WmiObject -Class Win32_LogicalDisk | Where-Object {$_.DriveType -eq 3}
foreach($drive in $drives) {
$totalGB = [math]::Round($drive.Size / 1GB, 2)
$freeGB = [math]::Round($drive.FreeSpace / 1GB, 2)
$freePercent = [math]::Round(($drive.FreeSpace / $drive.Size) * 100, 1)
$status = if($freePercent -gt 20) {"OK"} elseif($freePercent -gt 10) {"Warning"} else {"Critical"}
$statusClass = switch($status) {"OK"{"healthy"} "Warning"{"warning"} "Critical"{"critical"}}
Write-Host "$($drive.DeviceID) $totalGB GB total, $freeGB GB free ($freePercent%) - $status" -ForegroundColor $(switch($status) {"OK"{"Green"} "Warning"{"Yellow"} "Critical"{"Red"}})
$htmlReport += "<tr><td>$($drive.DeviceID)</td><td>$totalGB</td><td>$freeGB</td><td>$freePercent%</td><td class='$statusClass'>$status</td></tr>"
}
$htmlReport += "</table>"
# 5. Recent Errors
Write-Host "`n=== RECENT ERRORS ===" -ForegroundColor Green
$htmlReport += "<h3>Recent Errors (Last 24 Hours)</h3><table><tr><th>Time</th><th>Source</th><th>Event ID</th><th>Message</th></tr>"
$yesterday = (Get-Date).AddDays(-1)
$recentErrors = Get-EventLog -LogName Application -EntryType Error -After $yesterday |
Where-Object {$_.Source -like "*IIS*" -or $_.Source -like "*ASP.NET*"} |
Select-Object -First 10
if($recentErrors.Count -gt 0) {
foreach($error in $recentErrors) {
Write-Host "$($error.TimeGenerated) - $($error.Source) - $($error.EventID)" -ForegroundColor Red
$htmlReport += "<tr><td>$($error.TimeGenerated)</td><td>$($error.Source)</td><td>$($error.EventID)</td><td>$($error.Message.Substring(0, [math]::Min(100, $error.Message.Length)))...</td></tr>"
}
} else {
Write-Host "No recent IIS errors found" -ForegroundColor Green
$htmlReport += "<tr><td colspan='4'>No recent IIS errors found</td></tr>"
}
$htmlReport += "</table></div>"
# 6. Summary
$dailyEnd = Get-Date
$duration = $dailyEnd - $dailyStart
Write-Host "`n=== DAILY OPERATIONS SUMMARY ===" -ForegroundColor Cyan
$htmlReport += "<div class='section'><h2>Summary</h2>"
Write-Host "Check Duration: $($duration.TotalMinutes.ToString('F1')) minutes" -ForegroundColor White
Write-Host "Sites Checked: $($sites.Count)" -ForegroundColor White
Write-Host "Healthy Sites: $healthySites" -ForegroundColor Green
Write-Host "Warning Sites: $warningSites" -ForegroundColor Yellow
Write-Host "Critical Sites: $criticalSites" -ForegroundColor Red
$overallStatus = if($criticalSites -eq 0 -and $warningSites -eq 0) {"All Systems Operational"}
elseif($criticalSites -eq 0) {"Minor Issues Detected"}
else {"Critical Issues Require Attention"}
$statusClass = if($criticalSites -eq 0 -and $warningSites -eq 0) {"healthy"}
elseif($criticalSites -eq 0) {"warning"}
else {"critical"}
Write-Host "Overall Status: $overallStatus" -ForegroundColor $(switch($statusClass) {"healthy"{"Green"} "warning"{"Yellow"} "critical"{"Red"}})
$htmlReport += @"
<p><strong>Check Duration:</strong> $($duration.TotalMinutes.ToString('F1')) minutes</p>
<p><strong>Sites Checked:</strong> $($sites.Count)</p>
<p><strong>Healthy Sites:</strong> <span class="healthy">$healthySites</span></p>
<p><strong>Warning Sites:</strong> <span class="warning">$warningSites</span></p>
<p><strong>Critical Sites:</strong> <span class="critical">$criticalSites</span></p>
<p><strong>Overall Status:</strong> <span class="$statusClass">$overallStatus</span></p>
</div>
</body>
</html>
"@
# Save HTML report
$htmlReport | Out-File $reportFile -Encoding UTF8
Write-Host "`nDaily operations report saved: $reportFile" -ForegroundColor White
# Open report in browser
Start-Process $reportFile
} catch {
Write-Host "`nDAILY OPERATIONS ERROR: $($_.Exception.Message)" -ForegroundColor Red
}
}
# USAGE EXAMPLES:
# Daily check for production environment
Invoke-DailyOperations -Environment "production"
# Check all sites
Invoke-DailyOperations -Environment "all"
# Check test environment
Invoke-DailyOperations -Environment "test"
---
The functions in this guide provide:
ā Complete site monitoring with real-time dashboards
ā Smart restart capabilities with progressive recovery
ā Automated health checks with detailed reporting
ā Emergency response workflows for major incidents
ā Performance monitoring and analysis tools
ā Bulk operations for managing multiple sites
ā Daily operations automation and reporting
Quick deployment:
1. Copy all functions to your PowerShell profile
2. Run the Quick Start commands to test
3. Replace [YOUR_SITE_NAME]
placeholders with real site names
4. Set up monitoring for critical sites
Most useful for daily operations:
Watch-IISSite
for real-time monitoringTest-IISSiteHealth
for health checks Restart-IISSiteComplete
for reliable restartsInvoke-DailyOperations
for daily reportingStart-IISAutoRecovery
for automated recoveryAll functions include proper error handling, logging, and can be used in production environments.