1. [Prerequisites & Setup](#prerequisites--setup)
2. [Discovery Commands](#discovery-commands)
3. [Status & Health Checks](#status--health-checks)
4. [Configuration Management](#configuration-management)
5. [Application Pool Management](#application-pool-management)
6. [Site Management](#site-management)
7. [Security & Authentication](#security--authentication)
8. [Performance Monitoring](#performance-monitoring)
9. [Log Analysis](#log-analysis)
10. [Troubleshooting Commands](#troubleshooting-commands)
11. [Backup & Restore](#backup--restore)
12. [Network & Connectivity](#network--connectivity)
---
# Import IIS modules
ipmo WebAdministration,IISAdministration
# Verify modules loaded
gmo Web*,IIS* | select Name,Version
# Check if running as admin
([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator")
# Common aliases used in this guide
# gwc = Get-WebConfiguration
# swc = Set-WebConfiguration
# gsv = Get-Service
# gel = Get-EventLog
# gc = Get-Counter (perf) / Get-Content (files)
# gwmi = Get-WmiObject
# gci = Get-ChildItem
# gacl = Get-Acl
# select = Select-Object
# ? = Where-Object
# % = ForEach-Object
# ft = Format-Table
# fl = Format-List
---
# Basic site list
Get-IISSite | select Name,ID,State
# Detailed site info
Get-IISSite | select Name,ID,State,@{n="AppPool";e={$_.Applications[0].ApplicationPoolName}},@{n="Path";e={$_.Applications[0].VirtualDirectories[0].PhysicalPath}} | ft -Auto
# Sites with bindings
Get-IISSite | %{
$site = $_
$site | Get-IISSiteBinding | select @{n="Site";e={$site.Name}},Protocol,BindingInformation,SslFlags
} | ft -Auto
# Find site by name pattern
Get-IISSite | ?{$_.Name -like "*search*"}
# Sites and their states
Get-IISSite | group State | select Name,Count
# Find stopped sites
Get-IISSite | ?{$_.State -eq "Stopped"} | select Name,ID
# Basic app pool list
Get-IISAppPool | select Name,State
# Detailed app pool info
Get-IISAppPool | select Name,State,@{n="Identity";e={$_.ProcessModel.IdentityType}},@{n="User";e={$_.ProcessModel.UserName}},@{n=".NET";e={$_.ManagedRuntimeVersion}} | ft -Auto
# App pools and their sites
Get-IISAppPool | %{
$pool = $_
$sites = Get-IISSite | ?{$_.Applications[0].ApplicationPoolName -eq $pool.Name}
[PSCustomObject]@{
AppPool = $pool.Name
State = $pool.State
Sites = ($sites.Name -join ", ")
SiteCount = $sites.Count
}
} | ft -Auto
# Find stopped app pools
Get-IISAppPool | ?{$_.State -eq "Stopped"} | select Name,State
# App pools by .NET version
Get-IISAppPool | group ManagedRuntimeVersion | select Name,Count
# All site physical paths
Get-IISSite | select Name,@{n="PhysicalPath";e={$_.Applications[0].VirtualDirectories[0].PhysicalPath}}
# Check if paths exist
Get-IISSite | %{
$path = $_.Applications[0].VirtualDirectories[0].PhysicalPath
[PSCustomObject]@{
Site = $_.Name
Path = $path
Exists = (Test-Path $path)
Size = if(Test-Path $path){(gci $path -Recurse -File | measure Length -Sum).Sum/1MB}else{0}
}
} | ft -Auto
# Find web.config files
Get-IISSite | %{
$path = $_.Applications[0].VirtualDirectories[0].PhysicalPath
$config = Join-Path $path "web.config"
[PSCustomObject]@{
Site = $_.Name
ConfigExists = (Test-Path $config)
ConfigPath = $config
LastModified = if(Test-Path $config){(gi $config).LastWriteTime}else{"N/A"}
}
} | ft -Auto
---
# Core IIS services
gsv W3SVC,WAS,IISADMIN | select Name,Status,StartType
# All IIS-related services
gsv | ?{$_.Name -like "*IIS*" -or $_.DisplayName -like "*IIS*"} | select Name,Status,StartType
# Service dependencies
gsv W3SVC | select -ExpandProperty DependentServices
gsv W3SVC | select -ExpandProperty ServicesDependedOn
# Start/Stop services
# Start-Service W3SVC
# Stop-Service W3SVC
# Restart-Service W3SVC
# Active worker processes
gwmi Win32_Process -Filter "Name='w3wp.exe'" | select ProcessId,@{n="MemoryMB";e={[math]::Round($_.WS/1MB,2)}},@{n="CPU";e={$_.PageFileUsage}},CommandLine
# Worker processes with app pool names
Get-WmiObject -Query "SELECT * FROM Win32_Process WHERE Name='w3wp.exe'" | %{
$appPool = ($_.CommandLine -split '-ap "')[1] -replace '".*',''
[PSCustomObject]@{
ProcessId = $_.ProcessId
AppPool = $appPool
MemoryMB = [math]::Round($_.WorkingSetSize/1MB,2)
StartTime = $_.ConvertToDateTime($_.CreationDate)
}
} | ft -Auto
# Processes by memory usage
gwmi Win32_Process -Filter "Name='w3wp.exe'" | sort WorkingSetSize -Desc | select ProcessId,@{n="MemoryMB";e={[math]::Round($_.WS/1MB,2)}},CommandLine
# Check if any processes are hung
Get-Process w3wp -ea 0 | ?{$_.Responding -eq $false}
# Sites that should be running but aren't
Get-IISSite | ?{$_.State -ne "Started"} | select Name,State
# App pools that should be running but aren't
Get-IISAppPool | ?{$_.State -ne "Started"} | select Name,State
# Rapid-fail status
Get-IISAppPool | select Name,State,@{n="RapidFail";e={$_.Failure.RapidFailProtection}},@{n="FailureCount";e={$_.Failure.RapidFailProtectionMaxCrashes}}
# App pools with recent failures
Get-IISAppPool | ?{$_.Failure.RapidFailProtectionMaxCrashes -gt 0} | select Name,State,@{n="MaxCrashes";e={$_.Failure.RapidFailProtectionMaxCrashes}}
# Check app pool recycling conditions
Get-IISAppPool | select Name,@{n="IdleTimeout";e={$_.ProcessModel.IdleTimeout}},@{n="MemoryLimit";e={$_.Recycling.PeriodicRestart.Memory}},@{n="TimeInterval";e={$_.Recycling.PeriodicRestart.Time}}
---
# Site authentication methods
gwc "system.webserver/security/authentication/*" "IIS:\Sites\[SITE]" | ?{$_.enabled} | select SectionPath,Enabled
# Request filtering limits
gwc "system.webserver/security/requestFiltering/requestLimits" "IIS:\Sites\[SITE]" | select maxUrl,maxQueryString,maxAllowedContentLength
# Default documents
gwc "system.webserver/defaultDocument" "IIS:\Sites\[SITE]" | select enabled,@{n="Files";e={$_.files.collection.value -join ", "}}
# Handler mappings
gwc "system.webserver/handlers" "IIS:\Sites\[SITE]" | select name,path,verb,type | ft -Auto
# MIME types
gwc "system.webserver/staticContent" "IIS:\Sites\[SITE]" | select fileExtension,mimeType | ft -Auto
# Error pages
gwc "system.webserver/httpErrors" "IIS:\Sites\[SITE]" | select statusCode,subStatusCode,responseMode,path
# SSL settings
gwc "system.webserver/security/access" "IIS:\Sites\[SITE]" | select sslFlags
# Directory browsing
gwc "system.webserver/directoryBrowse" "IIS:\Sites\[SITE]" | select enabled
# IP restrictions
gwc "system.webserver/security/ipSecurity" "IIS:\Sites\[SITE]" | select allowUnlisted
# Check authentication across all sites
Get-IISSite | %{
$site = $_.Name
try {
$auth = gwc "system.webserver/security/authentication/*" "IIS:\Sites\$site" | ?{$_.enabled}
[PSCustomObject]@{
Site = $site
AuthMethods = ($auth.SectionPath -replace "system.webserver/security/authentication/","" -join ", ")
}
} catch {
[PSCustomObject]@{Site = $site; AuthMethods = "Error"}
}
} | ft -Auto
# SSL status across all sites
Get-IISSite | %{
$site = $_.Name
try {
$ssl = gwc "system.webserver/security/access" "IIS:\Sites\$site"
[PSCustomObject]@{
Site = $site
SSLRequired = $ssl.sslFlags -like "*Ssl*"
SSLFlags = $ssl.sslFlags
}
} catch {
[PSCustomObject]@{Site = $site; SSLRequired = "Error"; SSLFlags = "Error"}
}
} | ft -Auto
---
# Start all stopped app pools
Get-IISAppPool | ?{$_.State -eq "Stopped"} | %{Start-WebAppPool $_.Name; Write-Host "Started: $($_.Name)"}
# Stop specific app pool
Stop-WebAppPool "AppPoolName"
# Restart app pool
Restart-WebAppPool "AppPoolName"
# Reset rapid-fail count
Reset-WebAppPool "AppPoolName"
# Recycle app pool
Restart-WebAppPool "AppPoolName"
# Get app pool worker process
Get-IISAppPool "AppPoolName" | select Name,WorkerProcesses
# Get detailed app pool settings
Get-IISAppPool "AppPoolName" | select Name,State,ManagedRuntimeVersion,@{n="Identity";e={$_.ProcessModel.IdentityType}},@{n="IdleTimeout";e={$_.ProcessModel.IdleTimeout}}
# Change app pool identity
# swc "system.applicationHost/applicationPools/add[@name='AppPoolName']/processModel" @{identityType="ApplicationPoolIdentity"} "IIS:\"
# Change .NET version
# swc "system.applicationHost/applicationPools/add[@name='AppPoolName']" @{managedRuntimeVersion="v4.0"} "IIS:\"
# Enable 32-bit apps
# swc "system.applicationHost/applicationPools/add[@name='AppPoolName']" @{enable32BitAppOnWin64=$true} "IIS:\"
# Disable idle timeout
# swc "system.applicationHost/applicationPools/add[@name='AppPoolName']/processModel" @{idleTimeout="00:00:00"} "IIS:\"
---
# Start all stopped sites
Get-IISSite | ?{$_.State -eq "Stopped"} | %{Start-IISSite $_.Name; Write-Host "Started: $($_.Name)"}
# Stop specific site
Stop-IISSite "SiteName"
# Start specific site
Start-IISSite "SiteName"
# Remove site (be careful!)
# Remove-IISSite "SiteName" -Confirm:$false
# Create new site
# New-IISSite -Name "NewSite" -BindingInformation "*:8080:" -PhysicalPath "C:\inetpub\wwwroot\newsite"
# List all bindings
Get-IISSiteBinding | select SiteName,Protocol,BindingInformation,SslFlags | ft -Auto
# Bindings for specific site
Get-IISSiteBinding "SiteName" | select Protocol,BindingInformation,SslFlags
# Find sites using specific port
Get-IISSiteBinding | ?{$_.BindingInformation -like "*:80:*"} | select SiteName,BindingInformation
# Find HTTPS sites
Get-IISSiteBinding | ?{$_.Protocol -eq "https"} | select SiteName,BindingInformation,SslFlags
# Add HTTPS binding
# New-IISSiteBinding -Name "SiteName" -BindingInformation "*:443:" -Protocol https -SslFlag 1
---
# Check authentication methods per site
Get-IISSite | %{
$site = $_.Name
$auths = @()
try {
$anonymous = gwc "system.webserver/security/authentication/anonymousAuthentication" "IIS:\Sites\$site"
if($anonymous.enabled) {$auths += "Anonymous"}
$windows = gwc "system.webserver/security/authentication/windowsAuthentication" "IIS:\Sites\$site"
if($windows.enabled) {$auths += "Windows"}
$basic = gwc "system.webserver/security/authentication/basicAuthentication" "IIS:\Sites\$site"
if($basic.enabled) {$auths += "Basic"}
$forms = gwc "system.webserver/security/authentication/forms" "IIS:\Sites\$site"
if($forms.mode -eq "On") {$auths += "Forms"}
} catch {}
[PSCustomObject]@{
Site = $site
AuthMethods = $auths -join ", "
}
} | ft -Auto
# Check IIS_IUSRS permissions on all sites
Get-IISSite | %{
$path = $_.Applications[0].VirtualDirectories[0].PhysicalPath
if(Test-Path $path) {
$acl = gacl $path
$iisusers = $acl.Access | ?{$_.IdentityReference -like "*IIS_IUSRS*"}
[PSCustomObject]@{
Site = $_.Name
Path = $path
IIS_IUSRS_Rights = if($iisusers){$iisusers.FileSystemRights}else{"Missing"}
}
}
} | ft -Auto
# Check app pool identity permissions
Get-IISAppPool | %{
$poolName = $_.Name
$sites = Get-IISSite | ?{$_.Applications[0].ApplicationPoolName -eq $poolName}
foreach($site in $sites) {
$path = $site.Applications[0].VirtualDirectories[0].PhysicalPath
if(Test-Path $path) {
$acl = gacl $path
$poolIdentity = $acl.Access | ?{$_.IdentityReference -like "*$poolName*"}
[PSCustomObject]@{
AppPool = $poolName
Site = $site.Name
Path = $path
PoolIdentityRights = if($poolIdentity){$poolIdentity.FileSystemRights}else{"Missing"}
}
}
}
} | ft -Auto
---
# Key IIS performance counters
$counters = @(
"\Web Service(_Total)\Current Connections",
"\Web Service(_Total)\Requests/Sec",
"\ASP.NET Applications(__Total__)\Requests/Sec",
"\Process(w3wp)\% Processor Time",
"\Process(w3wp)\Working Set"
)
gc $counters -SampleInterval 2 -MaxSamples 5 | ft -Auto
# Memory usage of worker processes
Get-Process w3wp -ea 0 | select Id,ProcessName,@{n="MemoryMB";e={[math]::Round($_.WS/1MB,2)}},@{n="CPU%";e={$_.CPU}},StartTime | ft -Auto
# Connection counts per site
Get-IISSite | %{
try {
$counter = gc "\Web Service($($_.Name))\Current Connections" -SampleInterval 1 -MaxSamples 1 -ea 0
[PSCustomObject]@{
Site = $_.Name
CurrentConnections = $counter.CounterSamples[0].CookedValue
}
} catch {
[PSCustomObject]@{Site = $_.Name; CurrentConnections = "N/A"}
}
} | ft -Auto
# Request queue lengths
Get-IISAppPool | %{
try {
$counter = gc "\HTTP Service Request Queues($($_.Name))\CurrentQueueSize" -ea 0
[PSCustomObject]@{
AppPool = $_.Name
QueueSize = $counter.CounterSamples[0].CookedValue
}
} catch {
[PSCustomObject]@{AppPool = $_.Name; QueueSize = "N/A"}
}
} | ft -Auto
# Sample performance over time
$samples = 10
$interval = 5
Write-Host "Sampling for $($samples * $interval) seconds..."
1..$samples | %{
$timestamp = Get-Date
$workerProcs = Get-Process w3wp -ea 0
$totalMemory = ($workerProcs | measure -Property WS -Sum).Sum / 1MB
$connections = (gc "\Web Service(_Total)\Current Connections" -SampleInterval 1 -MaxSamples 1).CounterSamples[0].CookedValue
[PSCustomObject]@{
Time = $timestamp.ToString("HH:mm:ss")
WorkerProcesses = $workerProcs.Count
TotalMemoryMB = [math]::Round($totalMemory,2)
TotalConnections = $connections
}
Start-Sleep $interval
} | ft -Auto
---
# Find latest log file for site
$siteId = (Get-IISSite "SiteName").ID
$logPath = "C:\inetpub\logs\LogFiles\W3SVC$siteId"
$latestLog = gci $logPath -Filter "*.log" | sort LastWriteTime -Desc | select -First 1
# Get recent entries (last 100 lines)
gc $latestLog.FullName | select -Last 100
# Parse errors from logs
gc "$logPath\*.log" | ?{$_ -match " 5\d\d "} | select -Last 20
# Count status codes
gc $latestLog.FullName | ?{$_ -notlike "#*"} | %{($_ -split " ")[8]} | group | sort Count -Desc | select Name,Count
# Top IP addresses
gc $latestLog.FullName | ?{$_ -notlike "#*"} | %{($_ -split " ")[0]} | group | sort Count -Desc | select -First 10 Name,Count
# Requests by hour
gc $latestLog.FullName | ?{$_ -notlike "#*"} | %{($_ -split " ")[1].Substring(0,2)} | group | sort Name | select Name,Count
# Large responses (>1MB)
gc $latestLog.FullName | ?{$_ -notlike "#*" -and ($_ -split " ")[10] -gt 1048576} | %{
$fields = $_ -split " "
[PSCustomObject]@{
Time = $fields[1]
IP = $fields[0]
URL = $fields[4]
Status = $fields[8]
BytesSent = [math]::Round($fields[10]/1MB,2)
}
} | ft -Auto
# Recent IIS application errors
gel Application -EntryType Error -Newest 20 | ?{$_.Source -like "*IIS*" -or $_.Source -like "*ASP.NET*"} | select TimeGenerated,Source,EventID,Message
# W3SVC errors
gel System -Source "*W3SVC*" -EntryType Error -Newest 10 | select TimeGenerated,EventID,Message
# Application pool failures
gel System -Newest 50 | ?{$_.Message -like "*application pool*" -and $_.EntryType -eq "Error"} | select TimeGenerated,Message
# Authentication failures
gel Security -Newest 100 | ?{$_.EventID -eq 4625 -and $_.Message -like "*IIS*"} | select TimeGenerated,@{n="User";e={$_.ReplacementStrings[5]}},@{n="IP";e={$_.ReplacementStrings[19]}}
---
# Overall IIS health check
function Test-IISHealth {
Write-Host "=== IIS Health Check ===" -ForegroundColor Green
# Services
Write-Host "`nServices:" -ForegroundColor Yellow
gsv W3SVC,WAS | select Name,Status | ft -Auto
# Sites
Write-Host "Sites:" -ForegroundColor Yellow
Get-IISSite | group State | select Name,Count | ft -Auto
# App Pools
Write-Host "Application Pools:" -ForegroundColor Yellow
Get-IISAppPool | group State | select Name,Count | ft -Auto
# Worker Processes
Write-Host "Worker Processes:" -ForegroundColor Yellow
$procs = Get-Process w3wp -ea 0
if($procs) {
$procs | select Id,@{n="MemoryMB";e={[math]::Round($_.WS/1MB,2)}},StartTime | ft -Auto
} else {
Write-Host "No worker processes running" -ForegroundColor Red
}
# Recent Errors
Write-Host "Recent Application Errors:" -ForegroundColor Yellow
gel Application -EntryType Error -Newest 5 | ?{$_.Source -like "*IIS*" -or $_.Source -like "*ASP.NET*"} | select TimeGenerated,Source,Message | ft -Auto
}
# Run health check
Test-IISHealth
# Check port bindings
netstat -an | findstr ":80 \|:443 " | select -First 10
# Test if IIS is responding
try {
$response = Invoke-WebRequest "http://localhost" -UseBasicParsing -TimeoutSec 5
Write-Host "IIS responding: $($response.StatusCode)" -ForegroundColor Green
} catch {
Write-Host "IIS not responding: $($_.Exception.Message)" -ForegroundColor Red
}
# Check firewall for HTTP/HTTPS
Get-NetFirewallRule | ?{$_.DisplayName -like "*HTTP*" -or $_.DisplayName -like "*IIS*"} | select DisplayName,Enabled,Direction,Action
# Test web.config files
Get-IISSite | %{
$configPath = Join-Path $_.Applications[0].VirtualDirectories[0].PhysicalPath "web.config"
if(Test-Path $configPath) {
try {
[xml]$config = gc $configPath
[PSCustomObject]@{
Site = $_.Name
ConfigValid = $true
ConfigPath = $configPath
}
} catch {
[PSCustomObject]@{
Site = $_.Name
ConfigValid = $false
ConfigPath = $configPath
Error = $_.Exception.Message
}
}
}
} | ft -Auto
# Check for configuration conflicts
gwc "system.webserver" "IIS:\" | select SectionPath,OverrideMode | ?{$_.OverrideMode -eq "Deny"}
---
# Create configuration backup
$backupName = "IISBackup_$(Get-Date -Format 'yyyyMMdd_HHmmss')"
Backup-WebConfiguration -Name $backupName
Write-Host "Backup created: $backupName" -ForegroundColor Green
# List available backups
Get-WebConfigurationBackup | select Name,CreationDate | sort CreationDate -Desc
# Export specific site configuration
$siteName = "MySite"
$exportPath = "C:\Backup\$siteName_$(Get-Date -Format 'yyyyMMdd').xml"
gwc "system.applicationHost/sites/site[@name='$siteName']" "IIS:\" | Export-Clixml $exportPath
Write-Host "Site config exported to: $exportPath" -ForegroundColor Green
# Backup applicationHost.config
Copy-Item "$env:windir\System32\inetsrv\config\applicationHost.config" "C:\Backup\applicationHost_$(Get-Date -Format 'yyyyMMdd_HHmmss').config"
# Restore from backup (BE CAREFUL!)
# Restore-WebConfiguration -Name "BackupName"
# List configuration history
gwc "system.applicationHost/configHistory" "IIS:\" | select path,created | ft -Auto
# Compare current config with backup
# $current = gwc "system.applicationHost" "IIS:\"
# $backup = Import-Clixml "C:\Backup\config.xml"
# Compare-Object $current $backup
---
# All listening ports
netstat -an | ?{$_ -like "*LISTEN*"} | ?{$_ -like "*:80 *" -or $_ -like "*:443 *" -or $_ -like "*:8080 *"}
# IIS processes and their ports
Get-Process w3wp -ea 0 | %{
$proc = $_
$connections = netstat -ano | ?{$_ -like "*:80 *" -and $_ -like "*$($proc.Id)*"}
[PSCustomObject]@{
ProcessId = $proc.Id
Connections = $connections.Count
StartTime = $proc.StartTime
}
} | ft -Auto
# SSL certificate validation
Get-IISSiteBinding | ?{$_.Protocol -eq "https"} | %{
$binding = $_
try {
$cert = Get-ChildItem Cert:\LocalMachine\My | ?{$_.Thumbprint -eq $binding.certificateHash}
[PSCustomObject]@{
Site = $binding.SiteName
Binding = $binding.BindingInformation
CertSubject = $cert.Subject
CertExpiry = $cert.NotAfter
DaysUntilExpiry = ($cert.NotAfter - (Get-Date)).Days
Valid = $cert.NotAfter -gt (Get-Date)
}
} catch {
[PSCustomObject]@{
Site = $binding.SiteName
Binding = $binding.BindingInformation
CertSubject = "Error"
CertExpiry = "Error"
DaysUntilExpiry = "Error"
Valid = $false
}
}
} | ft -Auto
# Test local connectivity
Test-NetConnection localhost -Port 80
Test-NetConnection localhost -Port 443
# Check DNS resolution
Resolve-DnsName localhost
nslookup localhost
# Trace network path (if testing remote)
# Test-NetConnection remoteserver.com -Port 80 -TraceRoute
# Check network adapters
Get-NetAdapter | ?{$_.Status -eq "Up"} | select Name,InterfaceDescription,LinkSpeed
---
# Function to get complete site info
function Get-IISSiteInfo {
param([string]$SiteName = "*")
Get-IISSite | ?{$_.Name -like $SiteName} | %{
$site = $_
$appPool = Get-IISAppPool $site.Applications[0].ApplicationPoolName
$bindings = Get-IISSiteBinding $site.Name
[PSCustomObject]@{
SiteName = $site.Name
SiteID = $site.ID
SiteState = $site.State
PhysicalPath = $site.Applications[0].VirtualDirectories[0].PhysicalPath
AppPoolName = $appPool.Name
AppPoolState = $appPool.State
DotNetVersion = $appPool.ManagedRuntimeVersion
Bindings = ($bindings | %{"$($_.Protocol):$($_.BindingInformation)"}) -join ", "
SSL = ($bindings | ?{$_.Protocol -eq "https"}).Count -gt 0
}
} | ft -Auto
}
# Function to restart site and app pool
function Restart-IISSiteComplete {
param([string]$SiteName)
$site = Get-IISSite $SiteName
$poolName = $site.Applications[0].ApplicationPoolName
Write-Host "Stopping site: $SiteName" -ForegroundColor Yellow
Stop-IISSite $SiteName
Write-Host "Restarting app pool: $poolName" -ForegroundColor Yellow
Restart-WebAppPool $poolName
Start-Sleep 3
Write-Host "Starting site: $SiteName" -ForegroundColor Yellow
Start-IISSite $SiteName
Write-Host "Restart complete" -ForegroundColor Green
}
# Usage examples:
# Get-IISSiteInfo
# Get-IISSiteInfo "MyWebsite"
# Restart-IISSiteComplete "MyWebsite"