IIS Utility Functions - Usage Examples

🚨 IMPORTANT: REPLACE PLACEHOLDERS FIRST!

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:

Quick Reference:


# Find app pool names:
Get-IISAppPool | select Name

# Find app pool for specific site:
(Get-IISSite "[YOUR_SITE_NAME]").Applications[0].ApplicationPoolName

---

šŸš€ QUICK START - Copy & Paste Ready

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.

---

Table of Contents

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)

---

Discovery & Info Functions

Get-IISSiteInfo

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

Get-SiteStatus

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

---

Website Monitoring Functions

Watch-IISSite

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

Get-SitePerformance

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"

---

Restart & Recovery Functions

Restart-IISSiteComplete

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

Restart-AppPoolOnly

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

Invoke-SiteRecovery

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
}

---

Performance Monitoring

Show-SitePerformanceDashboard

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

---

Log Monitoring Functions

Watch-IISLogs

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"

---

Health Check Functions

Test-IISSiteHealth

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

---

Alerting & Notification Functions

Send-IISAlert

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

---

Automated Recovery Functions

Start-IISAutoRecovery

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

---

Bulk Management Functions

Invoke-BulkSiteOperation

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"

---

Real-World Scenarios

Complete Monitoring Setup


# 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

Deployment Pipeline Integration


# 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

Emergency Response Playbook


# 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"

Daily Operations Workflow


# 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"

---

šŸŽÆ Final Summary

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:

All functions include proper error handling, logging, and can be used in production environments.