# From web.config appSettings
Get-Website | ForEach-Object {
$webConfigPath = "$($_.PhysicalPath)\web.config"
if(Test-Path $webConfigPath) {
try {
[xml]$webConfig = Get-Content $webConfigPath
$webConfig.configuration.appSettings.add |
Where-Object {$_.key -match "email|mail|admin|alert"} |
Select-Object key, value
} catch {}
}
}
Get website URLs/base URLs:
# Get all website URLs from bindings
Get-Website | ForEach-Object {
$siteName = $_.Name
$_.Bindings.Collection | ForEach-Object {
$bindingParts = $_.bindingInformation -split ':'
$ip = $bindingParts[0]
$port = $bindingParts[1]
$hostname = $bindingParts[2]
if($hostname) {
$url = "$($_.Protocol)://$hostname"
if($port -ne "80" -and $port -ne "443") { $url += ":$port" }
} else {
$url = "$($_.Protocol)://localhost"
if($port -ne "80" -and $port -ne "443") { $url += ":$port" }
}
Write-Output "Site: $siteName | URL: $url"
}
}
Get HTTPS URLs only:
Get-Website | ForEach-Object {
$siteName = $_.Name
$_.Bindings.Collection | Where-Object {$_.Protocol -eq "https"} | ForEach-Object {
$bindingParts = $_.bindingInformation -split ':'
$hostname = if($bindingParts[2]) { $bindingParts[2] } else { "localhost" }
$port = $bindingParts[1]
$url = "https://$hostname"
if($port -ne "443") { $url += ":$port" }
Write-Output "Site: $siteName | HTTPS URL: $url"
}
}
Get website physical paths:
Get-Website | Select-Object Name, PhysicalPath
Get database server and database names from connection strings:
Get-Website | ForEach-Object {
$webConfigPath = "$($_.PhysicalPath)\web.config"
if(Test-Path $webConfigPath) {
try {
[xml]$webConfig = Get-Content $webConfigPath
$connections = $webConfig.configuration.connectionStrings.add
if($connections) {
$connections | ForEach-Object {
$connString = $_.connectionString
$server = if($connString -match "Server=([^;]+)") { $matches[1] } else { "Unknown" }
$database = if($connString -match "Database=([^;]+)") { $matches[1] } else { "Unknown" }
Write-Output "Site: $($_.Name) | Server: $server | Database: $database"
}
}
} catch {}
}
}
Get printer names:
Get-Printer | Select-Object Name, DriverName, PortName
Get LIMS file processing paths (common locations):
# Common LIMS file processing directories
$commonPaths = @(
"F:\LIMS\Data",
"F:\LIMS\Incoming",
"F:\LIMS\Processing",
"F:\LIMS\Archive",
"C:\LIMS\Data",
"D:\LIMS\Data"
)
foreach($path in $commonPaths) {
if(Test-Path $path) {
Write-Output "LIMS Path Found: $path"
Get-ChildItem $path -Directory | Select-Object Name, FullName
}
}
Get server name:
# Computer name
$env:COMPUTERNAME
# FQDN
[System.Net.Dns]::GetHostByName(($env:computerName)).HostName
Get URL patterns for monitoring:
# Extract URL patterns from website bindings
Get-Website | ForEach-Object {
$_.Bindings.Collection | ForEach-Object {
$bindingParts = $_.bindingInformation -split ':'
$hostname = $bindingParts[2]
if($hostname) {
Write-Output "URL Pattern: *$hostname*"
}
}
} | Sort-Object -Unique
Get service account passwords (NOTE: Cannot retrieve passwords - must be provided by admin):
# Service account passwords cannot be retrieved from system
# These must be obtained from:
# 1. Password manager/vault
# 2. Documentation
# 3. System administrator
Write-Output "Service account passwords must be provided by administrator"
Write-Output "Check: Password vault, documentation, or contact admin"
Before starting any IIS troubleshooting, ensure proper modules are available:
# Check available IIS modules
Get-Module -ListAvailable IIS*
Get-Module -ListAvailable WebAdministration
# Install IIS Management Scripts if missing
Install-WindowsFeature web-scripting-tools
Enable-WindowsOptionalFeature -Online -FeatureName IIS-ManagementScriptingTools
# Load required modules (run these commands first)
Import-Module WebAdministration -ErrorAction SilentlyContinue
Import-Module IISAdministration -ErrorAction SilentlyContinue
Add-PSSnapin WebAdministration -ErrorAction SilentlyContinue
---
Get all website names:
(Get-Website).Name
Get all website IDs:
Get-Website | Select-Object Name, ID
Get all application pool names:
(Get-IISAppPool).Name
Get application pool for specific website:
(Get-Website -Name "<WEBSITE_NAME>").ApplicationPool
Get all hostnames:
Get-Website | ForEach-Object { $_.Bindings.Collection | ForEach-Object { ($_.bindingInformation -split ':')[2] } } | Where-Object {$_ -ne ""}
Get log directory for specific site:
$site = Get-Website -Name "<WEBSITE_NAME>"
$logDir = $site.LogFile.Directory -replace '%SystemDrive%', $env:SystemDrive
"$logDir\W3SVC$($site.Id)"
Get worker process IDs:
(Get-Process w3wp -ErrorAction SilentlyContinue).Id
Get which app pool a worker process belongs to:
$pid = <PROCESS_ID>
$wpInfo = Get-WmiObject Win32_Process -Filter "ProcessId = $pid"
($wpInfo.CommandLine -split '"')[1]
Get physical path for website:
(Get-Website -Name "<WEBSITE_NAME>").PhysicalPath
Get server hostname:
$env:COMPUTERNAME
Get websites on F: drive:
Get-Website | Where-Object {$_.PhysicalPath -like "F:\*"} | Select-Object Name
Get SSL certificate thumbprints:
Get-ChildItem IIS:\SslBindings | Select-Object IPPort, Thumbprint
Get current IIS service status:
Get-Service W3SVC, WAS, HTTP | Select-Object Name, Status
Get database connection strings from web.config:
$sitePath = "<WEBSITE_PHYSICAL_PATH>"
$webConfigPath = "$sitePath\web.config"
if(Test-Path $webConfigPath) {
[xml]$webConfig = Get-Content $webConfigPath
$webConfig.configuration.connectionStrings.add | Select-Object name, connectionString
}
Get database connection strings from all websites:
Get-Website | ForEach-Object {
$webConfigPath = "$($_.PhysicalPath)\web.config"
if(Test-Path $webConfigPath) {
try {
[xml]$webConfig = Get-Content $webConfigPath
$connections = $webConfig.configuration.connectionStrings.add
if($connections) {
Write-Output "=== Site: $($_.Name) ==="
$connections | ForEach-Object { Write-Output "Name: $($_.name) | Connection: $($_.connectionString)" }
}
} catch {
Write-Output "Could not read web.config for $($_.Name)"
}
}
}
Get app settings from web.config:
$sitePath = "<WEBSITE_PHYSICAL_PATH>"
$webConfigPath = "$sitePath\web.config"
if(Test-Path $webConfigPath) {
[xml]$webConfig = Get-Content $webConfigPath
$webConfig.configuration.appSettings.add | Select-Object key, value
}
Find database server names in connection strings:
Get-Website | ForEach-Object {
$webConfigPath = "$($_.PhysicalPath)\web.config"
if(Test-Path $webConfigPath) {
try {
[xml]$webConfig = Get-Content $webConfigPath
$connections = $webConfig.configuration.connectionStrings.add
if($connections) {
$connections | ForEach-Object {
if($_.connectionString -match "Server=([^;]+)") {
Write-Output "Site: $($_.Name) | DB Server: $($matches[1])"
}
}
}
} catch {}
}
}
Get database connection strings from registry (some LIMS store here):
# Common registry locations for LIMS database settings
$regPaths = @(
"HKLM:\SOFTWARE\*\*\Database",
"HKLM:\SOFTWARE\WOW6432Node\*\*\Database"
)
foreach($path in $regPaths) {
Get-ChildItem $path -ErrorAction SilentlyContinue |
Get-ItemProperty |
Where-Object {$_.PSObject.Properties.Name -match "Server|Database|Connection"} |
Select-Object PSPath, *
}
Get service account names:
# Application pool service accounts
Get-IISAppPool | Select-Object Name, @{n='ServiceAccount';e={$_.ProcessModel.UserName}}
# Windows services (for LIMS background services)
Get-WmiObject Win32_Service | Where-Object {$_.Name -match "lims|lab|sample"} | Select-Object Name, StartName
Get domain name:
# Current domain
$env:USERDOMAIN
# Full domain name
(Get-WmiObject Win32_ComputerSystem).Domain
Get SSL certificate thumbprints:
# From IIS SSL bindings
Get-ChildItem IIS:\SslBindings | Select-Object IPPort, Thumbprint
# From certificate store
Get-ChildItem Cert:\LocalMachine\My | Select-Object Subject, Thumbprint, NotAfter
Get SMTP server settings:
# From web.config system.net mailSettings
Get-Website | ForEach-Object {
$webConfigPath = "$($_.PhysicalPath)\web.config"
if(Test-Path $webConfigPath) {
try {
[xml]$webConfig = Get-Content $webConfigPath
$smtp = $webConfig.configuration.'system.net'.mailSettings.smtp
if($smtp) {
Write-Output "Site: $($_.Name) | SMTP Host: $($smtp.network.host)"
}
} catch {}
}
}
Get admin email addresses from LIMS config:
# From web.config appSettings
Get-Website | ForEach-Object {
$webConfigPath = "$($_.PhysicalPath)\web.config"
if(Test-Path $webConfigPath) {
try {
[xml]$webConfig = Get-Content $webConfigPath
$webConfig.configuration.appSettings.add |
Where-Object {$_.key -match "email|mail|admin|alert"} |
Select-Object key, value
} catch {}
}
}
Discover application pool physical process information:
# Map worker processes to application pools
foreach($wp in Get-WmiObject -Class Win32_Process -Filter "Name='w3wp.exe'") {
$appPool = ($wp.CommandLine -split '"')[1]
[PSCustomObject]@{
ProcessId = $wp.ProcessId
AppPoolName = $appPool
StartTime = $wp.CreationDate
CommandLine = $wp.CommandLine
}
}
STEP 1: DISCOVER ALL WEBSITE NAMES AND DETAILS:
# Basic website discovery - THIS IS WHERE YOU GET SITE NAMES
Get-Website | Select-Object Name, ID, State, PhysicalPath, ApplicationPool
# Store site names for later use
$allSiteNames = (Get-Website).Name
Write-Output "Discovered website names:"
$allSiteNames | ForEach-Object { Write-Output " Site Name: '$_'" }
# Find LIMS-specific sites (likely on F: drive)
$limsSites = Get-Website | Where-Object {$_.PhysicalPath -like "F:\*"}
Write-Output "LIMS-related websites (F: drive):"
$limsSites | ForEach-Object {
Write-Output " Name: '$($_.Name)' | Path: '$($_.PhysicalPath)' | Pool: '$($_.ApplicationPool)'"
}
STEP 2: USE DISCOVERED SITE NAMES:
# Comprehensive website path discovery using DISCOVERED names
foreach($site in Get-Website) {
Write-Output "=== Site: $($site.Name) (ID: $($site.Id)) ==="
Write-Output "Main Path: $($site.PhysicalPath)"
Write-Output "Application Pool: $($site.ApplicationPool)"
# Get applications within the site
$apps = Get-WebApplication -Site $site.Name
if($apps) {
Write-Output "Applications:"
foreach($app in $apps) {
Write-Output " $($app.Path) -> $($app.PhysicalPath) [Pool: $($app.ApplicationPool)]"
}
}
# Get virtual directories
$vdirs = Get-WebVirtualDirectory -Site $site.Name
if($vdirs) {
Write-Output "Virtual Directories:"
foreach($vdir in $vdirs) {
Write-Output " $($vdir.Path) -> $($vdir.PhysicalPath)"
}
}
Write-Output ""
}
Find LIMS-specific paths (F: drive focus):
# Search for LIMS applications on F: drive
Get-Website | Where-Object {$_.PhysicalPath -like "F:\*"} |
Select-Object Name, PhysicalPath, ApplicationPool
# Find all IIS-related paths on F: drive
$fDrivePaths = @()
Get-Website | ForEach-Object {
if($_.PhysicalPath -like "F:\*") { $fDrivePaths += $_.PhysicalPath }
}
Get-WebApplication | ForEach-Object {
if($_.PhysicalPath -like "F:\*") { $fDrivePaths += $_.PhysicalPath }
}
$fDrivePaths | Sort-Object -Unique
STEP 1: DISCOVER SITE IDs AND NAMES:
# Get all site IDs and names first
Get-Website | Select-Object Name, ID, State | Format-Table -AutoSize
# Store site information for later use
$siteInfo = Get-Website | Select-Object Name, ID
$siteInfo | ForEach-Object {
Write-Output "Site Name: '$($_.Name)' has Site ID: '$($_.ID)'"
}
STEP 2: DISCOVER LOG LOCATIONS USING DISCOVERED SITE IDs:
# Standard log location discovery using actual discovered values
foreach($site in Get-Website) {
$logDir = $site.LogFile.Directory -replace '%SystemDrive%', $env:SystemDrive
$logPath = "$logDir\W3SVC$($site.Id)"
[PSCustomObject]@{
SiteName = $site.Name
SiteID = $site.Id
LogDirectory = $logPath
LogFormat = $site.LogFile.LogFormat
LogEnabled = $site.LogFile.Enabled
ActualLogPath = if(Test-Path $logPath) { $logPath } else { "Path Not Found" }
}
}
# Find all log files with recent activity
$logRoot = "$env:SystemDrive\inetpub\logs\LogFiles"
if(Test-Path $logRoot) {
Get-ChildItem $logRoot -Recurse -File |
Where-Object {$_.LastWriteTime -gt (Get-Date).AddDays(-7)} |
Select-Object Name, Directory, LastWriteTime,
@{n='SizeMB';e={[math]::Round($_.Length / 1MB, 2)}} |
Sort-Object LastWriteTime -Descending
}
Discover HTTPERR logs (critical for connection issues):
# HTTP.SYS error logs location
$httpErrPath = "$env:SystemRoot\System32\LogFiles\HTTPERR"
if(Test-Path $httpErrPath) {
Write-Output "HTTPERR Log Location: $httpErrPath"
Get-ChildItem $httpErrPath -File |
Select-Object Name, LastWriteTime,
@{n='SizeMB';e={[math]::Round($_.Length / 1MB, 2)}}
}
Discover website IDs and binding information:
# Complete binding discovery with hostname extraction
foreach($site in Get-Website) {
foreach($binding in $site.Bindings.Collection) {
$bindingParts = $binding.bindingInformation -split ':'
$ip = if($bindingParts[0] -eq '*') { 'All IPs' } else { $bindingParts[0] }
$port = $bindingParts[1]
$hostname = if($bindingParts[2]) { $bindingParts[2] } else { 'Any hostname' }
[PSCustomObject]@{
SiteName = $site.Name
SiteID = $site.Id
Protocol = $binding.Protocol
IPAddress = $ip
Port = $port
Hostname = $hostname
SSLFlags = $binding.sslFlags
PhysicalPath = $site.PhysicalPath
}
}
}
Extract unique hostnames for LIMS systems:
# Get all unique hostnames configured in IIS
$hostnames = @()
foreach($site in Get-Website) {
foreach($binding in $site.Bindings.Collection) {
$hostname = ($binding.bindingInformation -split ':')[2]
if($hostname -and $hostname -ne '') {
$hostnames += [PSCustomObject]@{
Hostname = $hostname
SiteName = $site.Name
Protocol = $binding.Protocol
}
}
}
}
$hostnames | Sort-Object Hostname -Unique
Discover authentication settings:
# Authentication configuration for each site
foreach($site in Get-Website) {
Write-Output "=== Authentication Settings for $($site.Name) ==="
# Anonymous Authentication
$anonymous = Get-WebConfigurationProperty -Filter "system.webServer/security/authentication/anonymousAuthentication" -Name "enabled" -Location $site.Name
Write-Output "Anonymous Authentication: $($anonymous.Value)"
# Windows Authentication
$windows = Get-WebConfigurationProperty -Filter "system.webServer/security/authentication/windowsAuthentication" -Name "enabled" -Location $site.Name
Write-Output "Windows Authentication: $($windows.Value)"
# Basic Authentication
$basic = Get-WebConfigurationProperty -Filter "system.webServer/security/authentication/basicAuthentication" -Name "enabled" -Location $site.Name
Write-Output "Basic Authentication: $($basic.Value)"
Write-Output ""
}
Discover SSL certificate bindings:
# SSL certificate discovery
Get-ChildItem IIS:\SslBindings | ForEach-Object {
$binding = $_
$cert = Get-ChildItem Cert:\LocalMachine\My | Where-Object {$_.Thumbprint -eq $binding.Thumbprint}
[PSCustomObject]@{
IPPort = $binding.IPPort
Hostname = $binding.Host
CertificateSubject = $cert.Subject
CertificateIssuer = $cert.Issuer
ExpirationDate = $cert.NotAfter
Thumbprint = $binding.Thumbprint
}
}
Master discovery script for LIMS environments:
# Complete IIS Discovery Script for LIMS Environments
# Save as Discover-IISEnvironment.ps1
param(
[switch]$IncludePerformanceData,
[switch]$ExportToFile
)
$timestamp = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
$reportPath = "C:\temp\IIS_Discovery_$timestamp.txt"
function Write-Section {
param([string]$Title)
$line = "=" * 50
$output = "`n$line`n$Title`n$line"
Write-Output $output
if($ExportToFile) { $output | Out-File $reportPath -Append }
}
function Write-Data {
param([string]$Data)
Write-Output $Data
if($ExportToFile) { $Data | Out-File $reportPath -Append }
}
# Ensure required modules are loaded
Import-Module WebAdministration -ErrorAction SilentlyContinue
Write-Section "IIS DISCOVERY REPORT - $(Get-Date)"
Write-Data "Server: $env:COMPUTERNAME"
Write-Data "Generated by: $env:USERNAME"
# System Information
Write-Section "SYSTEM INFORMATION"
$osInfo = Get-WmiObject Win32_OperatingSystem
Write-Data "OS: $($osInfo.Caption)"
Write-Data "Version: $($osInfo.Version)"
Write-Data "Architecture: $($osInfo.OSArchitecture)"
$iisVersion = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\InetStp' -ErrorAction SilentlyContinue)
if($iisVersion) {
Write-Data "IIS Version: $($iisVersion.VersionString)"
}
# Service Status
Write-Section "IIS SERVICE STATUS"
$services = @('HTTP', 'WAS', 'W3SVC', 'IISADMIN')
foreach($service in $services) {
$svc = Get-Service $service -ErrorAction SilentlyContinue
if($svc) {
Write-Data "$($svc.Name): $($svc.Status) [$($svc.StartType)]"
} else {
Write-Data "$service: Not Found"
}
}
# Websites Discovery
Write-Section "WEBSITES"
$websites = Get-Website
foreach($site in $websites) {
Write-Data "Site: $($site.Name) [ID: $($site.Id)]"
Write-Data " State: $($site.State)"
Write-Data " Physical Path: $($site.PhysicalPath)"
Write-Data " Application Pool: $($site.ApplicationPool)"
# Log information
$logDir = $site.LogFile.Directory -replace '%SystemDrive%', $env:SystemDrive
Write-Data " Log Directory: $logDir\W3SVC$($site.Id)"
Write-Data " Log Enabled: $($site.LogFile.Enabled)"
# Bindings
Write-Data " Bindings:"
foreach($binding in $site.Bindings.Collection) {
Write-Data " $($binding.Protocol): $($binding.bindingInformation)"
}
# Applications
$apps = Get-WebApplication -Site $site.Name
if($apps) {
Write-Data " Applications:"
foreach($app in $apps) {
Write-Data " $($app.Path) -> $($app.PhysicalPath) [Pool: $($app.ApplicationPool)]"
}
}
Write-Data ""
}
# Application Pools
Write-Section "APPLICATION POOLS"
$appPools = Get-ChildItem IIS:\AppPools
foreach($pool in $appPools) {
Write-Data "Pool: $($pool.Name)"
Write-Data " State: $($pool.State)"
Write-Data " .NET Version: $($pool.managedRuntimeVersion)"
Write-Data " Pipeline Mode: $($pool.managedPipelineMode)"
Write-Data " Identity: $($pool.processModel.identityType)"
Write-Data " Auto Start: $($pool.autoStart)"
Write-Data ""
}
# Worker Processes
Write-Section "WORKER PROCESSES"
$workerProcesses = Get-Process w3wp -ErrorAction SilentlyContinue
if($workerProcesses) {
foreach($wp in $workerProcesses) {
$appPool = "Unknown"
$wpInfo = Get-WmiObject -Class Win32_Process -Filter "ProcessId = $($wp.Id)" -ErrorAction SilentlyContinue
if($wpInfo) {
$appPool = ($wpInfo.CommandLine -split '"')[1]
}
Write-Data "PID: $($wp.Id) | App Pool: $appPool | CPU: $($wp.CPU) | Memory: $([math]::Round($wp.WorkingSet / 1MB, 2)) MB"
}
} else {
Write-Data "No worker processes currently running"
}
# Performance Data (if requested)
if($IncludePerformanceData) {
Write-Section "PERFORMANCE COUNTERS"
try {
$counters = Get-Counter -Counter @(
"\Processor(_Total)\% Processor Time",
"\Memory\Available MBytes",
"\Web Service(_Total)\Current Connections"
) -SampleInterval 1 -MaxSamples 1 -ErrorAction SilentlyContinue
foreach($counter in $counters.CounterSamples) {
Write-Data "$($counter.Path): $($counter.CookedValue)"
}
} catch {
Write-Data "Could not retrieve performance counters"
}
}
# Log File Analysis
Write-Section "LOG FILE ANALYSIS"
$logRoot = "$env:SystemDrive\inetpub\logs\LogFiles"
if(Test-Path $logRoot) {
$logStats = Get-ChildItem $logRoot -Recurse -File | Measure-Object -Property Length -Sum
Write-Data "Total log files: $($logStats.Count)"
Write-Data "Total log size: $([math]::Round($logStats.Sum / 1MB, 2)) MB"
# Recent activity
$recentLogs = Get-ChildItem $logRoot -Recurse -File |
Where-Object {$_.LastWriteTime -gt (Get-Date).AddDays(-1)} |
Sort-Object LastWriteTime -Descending |
Select-Object -First 5
Write-Data "Recent log files (last 24 hours):"
foreach($log in $recentLogs) {
Write-Data " $($log.Name) - Modified: $($log.LastWriteTime)"
}
}
# SSL Certificates
Write-Section "SSL CERTIFICATES"
$sslBindings = Get-ChildItem IIS:\SslBindings -ErrorAction SilentlyContinue
if($sslBindings) {
foreach($binding in $sslBindings) {
$cert = Get-ChildItem Cert:\LocalMachine\My | Where-Object {$_.Thumbprint -eq $binding.Thumbprint}
if($cert) {
Write-Data "Binding: $($binding.IPPort)"
Write-Data " Subject: $($cert.Subject)"
Write-Data " Expires: $($cert.NotAfter)"
Write-Data " Thumbprint: $($binding.Thumbprint)"
}
}
} else {
Write-Data "No SSL bindings configured"
}
Write-Section "DISCOVERY COMPLETE"
if($ExportToFile) {
Write-Output "Report saved to: $reportPath"
}
# Usage Examples:
# .\Discover-IISEnvironment.ps1
# .\Discover-IISEnvironment.ps1 -IncludePerformanceData
# .\Discover-IISEnvironment.ps1 -ExportToFile
---
Analyze IIS access logs for patterns:
# Find recent errors in IIS logs
$logPath = "<LOG_DIRECTORY_PATH>" # Example: C:\inetpub\logs\LogFiles\W3SVC1
$yesterday = (Get-Date).AddDays(-1)
Get-ChildItem "$logPath\*.log" |
Where-Object {$_.LastWriteTime -gt $yesterday} |
ForEach-Object {
$content = Get-Content $_.FullName |
Where-Object {$_ -notlike "#*" -and $_ -match " (4[0-9][0-9]|5[0-9][0-9]) "}
foreach($line in $content) {
$fields = $line -split ' '
if($fields.Count -ge 9) {
[PSCustomObject]@{
DateTime = "$($fields[0]) $($fields[1])"
ClientIP = $fields[2]
Method = $fields[3]
UriStem = $fields[4]
StatusCode = $fields[8]
TimeTaken = $fields[14]
LogFile = $_.Name
}
}
}
} | Sort-Object DateTime -Descending | Select-Object -First 50
Analyze HTTPERR logs for connection issues:
# Parse HTTPERR logs for connection resets (common in LIMS)
$httpErrPath = "$env:SystemRoot\System32\LogFiles\HTTPERR"
$yesterday = (Get-Date).AddDays(-1)
if(Test-Path $httpErrPath) {
Get-ChildItem "$httpErrPath\httperr*.log" |
Where-Object {$_.LastWriteTime -gt $yesterday} |
ForEach-Object {
Get-Content $_.FullName | Where-Object {$_ -match "Connection_Abandoned_By_ReqQueue|Timer_ConnectionIdle"}
} | Select-Object -First 20
}
Analyze application pool performance:
# Get application pool performance metrics
$appPoolName = "<APPLICATION_POOL_NAME>"
# Check if application pool is healthy
$appPool = Get-IISAppPool -Name $appPoolName
Write-Output "Application Pool '$appPoolName' State: $($appPool.State)"
# Get worker process information
$workerProcess = Get-Process w3wp -ErrorAction SilentlyContinue |
Where-Object {
$wpInfo = Get-WmiObject Win32_Process -Filter "ProcessId = $($_.Id)"
($wpInfo.CommandLine -split '"')[1] -eq $appPoolName
}
if($workerProcess) {
[PSCustomObject]@{
AppPool = $appPoolName
ProcessId = $workerProcess.Id
CPUTime = $workerProcess.CPU
WorkingSetMB = [math]::Round($workerProcess.WorkingSet / 1MB, 2)
StartTime = $workerProcess.StartTime
ThreadCount = $workerProcess.Threads.Count
}
}
STEP 1: DISCOVER APPLICATION POOL NAMES FIRST:
# Get all application pool names
$appPoolNames = (Get-IISAppPool).Name
Write-Output "Available Application Pools:"
$appPoolNames | ForEach-Object { Write-Output " - $_" }
# Filter for LIMS-related application pools (common naming patterns)
$limsAppPools = $appPoolNames | Where-Object {$_ -match "lims|lab|laboratory|sample"}
Write-Output "Potential LIMS Application Pools:"
$limsAppPools | ForEach-Object { Write-Output " - $_" }
STEP 2: MONITOR DISCOVERED APPLICATION POOLS:
# Monitor application pool resource usage over time
# TIME UNITS: $samples = number of measurements, $interval = SECONDS between measurements
$samples = 5 # Take 5 measurements
$interval = 10 # Wait 10 SECONDS between each measurement (total monitoring time = 50 seconds)
# Choose application pool to monitor from discovered list
foreach($appPoolName in (Get-IISAppPool).Name) {
Write-Output "=== Monitoring Application Pool: $appPoolName ==="
for($i = 1; $i -le $samples; $i++) {
$wp = Get-Process w3wp -ErrorAction SilentlyContinue |
Where-Object {
$wpInfo = Get-WmiObject Win32_Process -Filter "ProcessId = $($_.Id)"
($wpInfo.CommandLine -split '"')[1] -eq $appPoolName
}
if($wp) {
Write-Output "Sample $i - Memory: $([math]::Round($wp.WorkingSet / 1MB, 2)) MB | Threads: $($wp.Threads.Count)"
if($i -lt $samples) { Start-Sleep $interval } # Sleep for $interval SECONDS
} else {
Write-Output "Sample $i - No worker process found for app pool: $appPoolName"
}
}
Write-Output ""
}
### 3. Configuration Analysis
**Compare current configuration with baseline:**
$siteName = "
$configPath = "C:\temp\IIS_Config_$(Get-Date -Format 'yyyy-MM-dd').xml"
$siteConfig = Get-WebConfiguration -Filter "system.applicationHost/sites/site[@name='$siteName']"
$siteConfig | Export-Clixml $configPath
$appPoolName = (Get-Website -Name $siteName).ApplicationPool
$appPoolConfig = Get-WebConfiguration -Filter "system.applicationHost/applicationPools/add[@name='$appPoolName']"
$appPoolConfig | Export-Clixml "C:\temp\AppPool_Config_$(Get-Date -Format 'yyyy-MM-dd').xml"
Write-Output "Configuration exported to $configPath"
---
## IIS Debugging Scenarios for LIMS
### 1. Web Service Failures
#### Scenario: LIMS API Connection Resets
**Symptoms:**
- HTTP API calls fail intermittently
- "Connection_Abandoned_By_ReqQueue" in HTTPERR logs
- Requires server restart to resolve temporarily
**Discovery Commands:**
$httpErrPath = "$env:SystemRoot\System32\LogFiles\HTTPERR"
Get-ChildItem "$httpErrPath\httperr*.log" |
ForEach-Object {
Get-Content $_.FullName |
Where-Object {$_ -match "Connection_Abandoned_By_ReqQueue"} |
Select-Object -Last 10
}
$appPoolName = "
Get-IISAppPool -Name $appPoolName | Select-Object Name, ProcessModel
netsh http show servicestate view=requestq verbose=yes
**Diagnosis Commands:**
$siteName = "
appcmd list requests /site.name:"$siteName" /elapsed:10000
$appPoolName = "
Get-Counter "\ASP.NET Applications($appPoolName)\Requests Executing" -MaxSamples 5 -SampleInterval 2
**Resolution Steps:**
appcmd set config -section:system.webServer/httpErrors /+"[statusCode='503',subStatusCode='2',prefixLanguageFilePath='',path='C:\inetpub\custerr\en-US\503.htm']"
$appPoolName = "
Set-ItemProperty -Path "IIS:\AppPools\$appPoolName" -Name processModel.identityType -Value SpecificUser
Set-ItemProperty -Path "IIS:\AppPools\$appPoolName" -Name processModel.userName -Value "
Set-ItemProperty -Path "IIS:\AppPools\$appPoolName" -Name processModel.password -Value "
$siteName = "
Set-WebConfigurationProperty -Filter "system.webServer/httpProtocol" -Name "allowKeepAlive" -Value $true -Location $siteName
#### Scenario: Web Service Hangs and Timeouts
**Symptoms:**
- Pages taking >30 seconds to load
- 503 Service Unavailable errors
- High CPU usage in w3wp.exe
**Discovery Commands:**
$siteName = "
appcmd list requests /site.name:"$siteName" /elapsed:30000
$appPoolName = "
Get-Counter "\ASP.NET Applications($appPoolName)\Requests in Application Queue" -MaxSamples 3
$appPoolName = "
Get-Process w3wp | Where-Object {
$wpInfo = Get-WmiObject Win32_Process -Filter "ProcessId = $($_.Id)"
($wpInfo.CommandLine -split '"')[1] -eq $appPoolName
} | Measure-Object CPU -Average
**Resolution Commands:**
$siteName = "
Set-WebConfigurationProperty -Filter "system.web/httpRuntime" -Name "executionTimeout" -Value 300 -Location $siteName
Set-WebConfigurationProperty -Filter "system.web/httpRuntime" -Name "maxRequestLength" -Value 102400 -Location $siteName
$appPoolName = "
Set-ItemProperty -Path "IIS:\AppPools\$appPoolName" -Name recycling.periodicRestart.requests -Value 10000
Set-ItemProperty -Path "IIS:\AppPools\$appPoolName" -Name recycling.periodicRestart.privateMemory -Value 1048576 # 1GB in KB
### 2. API Connectivity Problems
#### Scenario: LIMS Database Integration Failures
**Symptoms:**
- "Cannot locate master LIM now" error messages
- Database timeout exceptions
- Intermittent data access failures
**Discovery Commands:**
$connectionString = "
try {
$connection = New-Object System.Data.SqlClient.SqlConnection($connectionString)
$connection.Open()
Write-Output "Database connection successful"
$connection.Close()
} catch {
Write-Output "Database connection failed: $($_.Exception.Message)"
}
$appPoolName = "
$appPool = Get-IISAppPool -Name $appPoolName
Write-Output "Application Pool Identity: $($appPool.ProcessModel.IdentityType)"
**Resolution Commands:**
$webConfigPath = "
$webConfig = [xml](Get-Content $webConfigPath)
$connectionString = "Server=
Copy-Item $webConfigPath "$webConfigPath.backup"
Write-Output "Update connection string in $webConfigPath with proper pooling settings"
### 3. File Receiving Issues
#### Scenario: LIMS File Processing Service Failures
**Symptoms:**
- Files accumulating in watch folders
- "System resource exceeded" errors
- File system access denied errors
**Discovery Commands:**
$limsPath = "
$appPoolName = "
$identity = "IIS AppPool\$appPoolName"
Write-Output "Checking permissions for: $identity"
$acl = Get-Acl $limsPath
$acl.AccessToString
$testFile = Join-Path $limsPath "test_$(Get-Date -Format 'yyyyMMdd_HHmmss').txt"
try {
"Test" | Out-File $testFile
Remove-Item $testFile
Write-Output "File system permissions: OK"
} catch {
Write-Output "File system permissions: FAILED - $($_.Exception.Message)"
}
**Resolution Commands:**
$limsPath = "
$appPoolName = "
$identity = "IIS AppPool\$appPoolName"
icacls "$limsPath" /grant "$identity:(OI)(CI)F" /T
Write-Output "Add the following paths to antivirus exclusions:"
Write-Output "- $limsPath"
Write-Output "- F:\LIMS\*" # Adjust based on your LIMS installation
### 4. Printer Agent Problems
#### Scenario: LIMS Label Printing Service Issues
**Symptoms:**
- Print jobs stuck in queue
- "ApplicationPoolIdentity" printer access errors
- Registry key missing printer information
**Discovery Commands:**
$appPoolName = "
$identity = "IIS AppPool\$appPoolName"
Get-Printer | Select-Object Name, DriverName, PortName, PrinterStatus
$printerName = "
try {
$printer = Get-Printer -Name $printerName
Write-Output "Printer '$printerName' found: $($printer.PrinterStatus)"
} catch {
Write-Output "Cannot access printer '$printerName': $($_.Exception.Message)"
}
**Resolution Commands:**
$appPoolName = "
Set-ItemProperty -Path "IIS:\AppPools\$appPoolName" -Name processModel.loadUserProfile -Value $true
Set-ItemProperty -Path "IIS:\AppPools\$appPoolName" -Name processModel.identityType -Value SpecificUser
Set-ItemProperty -Path "IIS:\AppPools\$appPoolName" -Name processModel.userName -Value "
Set-ItemProperty -Path "IIS:\AppPools\$appPoolName" -Name processModel.password -Value "
$siteName = "
Set-WebConfigurationProperty -Filter "system.webServer/security/requestFiltering/requestLimits" -Name maxAllowedContentLength -Value 104857600 -Location $siteName # 100MB
### 5. Authentication and Authorization Issues
#### Scenario: LIMS Single Sign-On Failures
**Symptoms:**
- 401.2 authentication errors
- Kerberos double-hop issues
- Users unable to access LIMS modules
**Discovery Commands:**
$siteName = "
Get-WebConfigurationProperty -Filter "system.webServer/security/authentication/windowsAuthentication" -Name "enabled" -Location $siteName
Get-WebConfigurationProperty -Filter "system.webServer/security/authentication/windowsAuthentication/providers" -Location $siteName
$serviceName = "
$serverName = "
setspn -L $serviceName
setspn -Q HTTP/$serverName
**Resolution Commands:**
$siteName = "
Set-WebConfigurationProperty -Filter "system.webServer/security/authentication/windowsAuthentication" -Name "enabled" -Value $true -Location $siteName
Add-WebConfigurationProperty -Filter "system.webServer/security/authentication/windowsAuthentication/providers" -Name "." -Value @{value="Negotiate"} -Location $siteName
$serviceName = "
$serverName = "
setspn -A HTTP/$serverName $serviceName
setspn -A HTTP/$serverName.domain.com $serviceName
Write-Output "Configure constrained delegation in Active Directory for account: $serviceName"
---
## Advanced Troubleshooting
### 1. Memory Leaks and Performance Issues
**Detect memory leaks in LIMS applications:**
$appPoolName = "
$monitorMinutes = 30
$intervalSeconds = 60
$results = @()
for($i = 0; $i -lt $monitorMinutes; $i++) {
$wp = Get-Process w3wp -ErrorAction SilentlyContinue |
Where-Object {
$wpInfo = Get-WmiObject Win32_Process -Filter "ProcessId = $($_.Id)"
($wpInfo.CommandLine -split '"')[1] -eq $appPoolName
}
if($wp) {
$results += [PSCustomObject]@{
Time = Get-Date
MemoryMB = [math]::Round($wp.WorkingSet / 1MB, 2)
ThreadCount = $wp.Threads.Count
HandleCount = $wp.HandleCount
CPUTime = $wp.CPU
}
}
if($i -lt ($monitorMinutes - 1)) { Start-Sleep $intervalSeconds }
}
$results | Format-Table -AutoSize
$memoryGrowth = ($results[-1].MemoryMB - $results[0].MemoryMB)
Write-Output "Memory growth over $monitorMinutes minutes: $memoryGrowth MB"
**Configure memory-based recycling:**
$appPoolName = "
$memoryLimitMB = 2048 # 2GB
Set-ItemProperty -Path "IIS:\AppPools\$appPoolName" -Name recycling.periodicRestart.privateMemory -Value ($memoryLimitMB * 1024) # Convert to KB
Set-ItemProperty -Path "IIS:\AppPools\$appPoolName" -Name recycling.periodicRestart.virtualMemory -Value ($memoryLimitMB 1024 2) # 4GB virtual
### 2. SSL/TLS Configuration Problems
**Diagnose SSL certificate issues:**
$hostname = "
$port = 443
$tcpClient = New-Object System.Net.Sockets.TcpClient
try {
$tcpClient.Connect($hostname, $port)
$sslStream = New-Object System.Net.Security.SslStream($tcpClient.GetStream())
$sslStream.AuthenticateAsClient($hostname)
$cert = $sslStream.RemoteCertificate
[PSCustomObject]@{
Subject = $cert.Subject
Issuer = $cert.Issuer
ValidFrom = [datetime]$cert.GetEffectiveDateString()
ValidTo = [datetime]$cert.GetExpirationDateString()
DaysUntilExpiry = ([datetime]$cert.GetExpirationDateString() - (Get-Date)).Days
Thumbprint = $cert.GetCertHashString()
}
$sslStream.Close()
} catch {
Write-Output "SSL connection failed: $($_.Exception.Message)"
} finally {
$tcpClient.Close()
}
**Fix SSL binding issues:**
$siteName = "
$certificateThumbprint = "
$ipAddress = "*" # or specific IP
$port = 443
Remove-WebBinding -Name $siteName -Protocol https -Port $port -IPAddress $ipAddress
New-WebBinding -Name $siteName -Protocol https -Port $port -IPAddress $ipAddress
New-Item -Path "IIS:\SslBindings\$ipAddress!$port" -Value (Get-ChildItem Cert:\LocalMachine\My | Where-Object {$_.Thumbprint -eq $certificateThumbprint})
### 3. Network Connectivity Debugging
**Test LIMS API endpoints:**
function Test-LIMSConnectivity {
param(
[string]$BaseUrl = "
[string[]]$Endpoints = @("api/status", "api/health", "api/version"),
[int]$TimeoutSeconds = 30
)
$results = @()
foreach($endpoint in $endpoints) {
$fullUrl = "$BaseUrl/$endpoint"
try {
$stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
$response = Invoke-WebRequest -Uri $fullUrl -TimeoutSec $TimeoutSeconds -UseBasicParsing
$stopwatch.Stop()
$results += [PSCustomObject]@{
Endpoint = $endpoint
Status = "Success"
StatusCode = $response.StatusCode
ResponseTime = $stopwatch.ElapsedMilliseconds
ContentLength = $response.Content.Length
}
} catch {
$results += [PSCustomObject]@{
Endpoint = $endpoint
Status = "Failed"
StatusCode = $_.Exception.Response.StatusCode.value__
Error = $_.Exception.Message
ResponseTime = $null
ContentLength = $null
}
}
}
return $results
}
Test-LIMSConnectivity -BaseUrl "
**Trace network issues:**
$traceFile = "C:\temp\lims_network_trace.etl"
netsh trace start capture=yes provider=Microsoft-Windows-HttpService tracefile=$traceFile maxsize=100
Write-Output "Network trace started. Reproduce the issue, then run:"
Write-Output "netsh trace stop"
Write-Output "Trace file: $traceFile"
netsh http show urlacl | Where-Object {$_ -match "
netsh http show sslcert | Where-Object {$_ -match "
### 4. Complete Health Check Script
**Comprehensive LIMS-IIS health monitoring:**
param(
[string]$LIMSSiteName = "
[string]$LIMSAppPoolName = "
[string]$LIMSBaseUrl = "
[switch]$Detailed
)
function Write-Status {
param([string]$Component, [string]$Status, [string]$Details = "")
$color = switch($Status) {
"OK" { "Green" }
"WARNING" { "Yellow" }
"ERROR" { "Red" }
default { "White" }
}
Write-Host "[$Status] $Component" -ForegroundColor $color
if($Details) { Write-Host " $Details" -ForegroundColor Gray }
}
Write-Host "=== LIMS-IIS Health Check ===" -ForegroundColor Cyan
Write-Host "Site: $LIMSSiteName" -ForegroundColor Cyan
Write-Host "App Pool: $LIMSAppPoolName" -ForegroundColor Cyan
Write-Host "URL: $LIMSBaseUrl" -ForegroundColor Cyan
Write-Host ""
$services = @('HTTP', 'WAS', 'W3SVC')
foreach($service in $services) {
$svc = Get-Service $service -ErrorAction SilentlyContinue
if($svc -and $svc.Status -eq 'Running') {
Write-Status "$service Service" "OK" "Running"
} else {
Write-Status "$service Service" "ERROR" "Not running or not found"
}
}
try {
$website = Get-Website -Name $LIMSSiteName
if($website.State -eq 'Started') {
Write-Status "Website $LIMSSiteName" "OK" "Started"
} else {
Write-Status "Website $LIMSSiteName" "ERROR" "State: $($website.State)"
}
} catch {
Write-Status "Website $LIMSSiteName" "ERROR" "Not found"
}
try {
$appPool = Get-IISAppPool -Name $LIMSAppPoolName
if($appPool.State -eq 'Started') {
Write-Status "App Pool $LIMSAppPoolName" "OK" "Started"
} else {
Write-Status "App Pool $LIMSAppPoolName" "ERROR" "State: $($appPool.State)"
}
} catch {
Write-Status "App Pool $LIMSAppPoolName" "ERROR" "Not found"
}
$wp = Get-Process w3wp -ErrorAction SilentlyContinue |
Where-Object {
$wpInfo = Get-WmiObject Win32_Process -Filter "ProcessId = $($_.Id)"
($wpInfo.CommandLine -split '"')[1] -eq $LIMSAppPoolName
}
if($wp) {
$memoryMB = [math]::Round($wp.WorkingSet / 1MB, 2)
if($memoryMB -lt 1000) {
Write-Status "Worker Process Memory" "OK" "$memoryMB MB"
} elseif($memoryMB -lt 2000) {
Write-Status "Worker Process Memory" "WARNING" "$memoryMB MB"
} else {
Write-Status "Worker Process Memory" "ERROR" "$memoryMB MB (High)"
}
} else {
Write-Status "Worker Process" "WARNING" "No worker process found"
}
try {
$response = Invoke-WebRequest -Uri $LIMSBaseUrl -TimeoutSec 10 -UseBasicParsing
if($response.StatusCode -eq 200) {
Write-Status "Web Connectivity" "OK" "HTTP $($response.StatusCode)"
} else {
Write-Status "Web Connectivity" "WARNING" "HTTP $($response.StatusCode)"
}
} catch {
Write-Status "Web Connectivity" "ERROR" $_.Exception.Message
}
if($Detailed) {
Write-Host "`n=== Recent Errors (Last Hour) ===" -ForegroundColor Cyan
$recentErrors = Get-WinEvent -FilterHashtable @{
LogName='Application'
StartTime=(Get-Date).AddHours(-1)
Level=2
} -MaxEvents 5 -ErrorAction SilentlyContinue |
Where-Object {$_.ProviderName -match 'IIS|ASP.NET|W3SVC'}
if($recentErrors) {
foreach($error in $recentErrors) {
Write-Host "$($error.TimeCreated): $($error.LevelDisplayName) - $($error.Message.Substring(0, [Math]::Min(100, $error.Message.Length)))..." -ForegroundColor Red
}
} else {
Write-Host "No recent errors found" -ForegroundColor Green
}
}
Write-Host "`n=== Health Check Complete ===" -ForegroundColor Cyan
---
## Prevention and Monitoring
### 1. Proactive Monitoring Setup
**Configure performance counter monitoring:**
$monitoringScript = @"
`$counters = @(
"\Web Service(_Total)\Current Connections",
"\ASP.NET Applications(
"\ASP.NET Applications(
"\Process(w3wp*)\% Processor Time",
"\Process(w3wp*)\Working Set"
)
Get-Counter -Counter `$counters -SampleInterval 30 -MaxSamples 120 |
Export-Counter -Path "C:\temp\LIMS_Performance_`$(Get-Date -Format 'yyyy-MM-dd_HH-mm').blg"
"@
$monitoringScript | Out-File "C:\scripts\Monitor-LIMS-Performance.ps1"
$action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-File C:\scripts\Monitor-LIMS-Performance.ps1"
$trigger = New-ScheduledTaskTrigger -Daily -At "08:00AM"
Register-ScheduledTask -TaskName "LIMS Performance Monitoring" -Action $action -Trigger $trigger -Description "Monitor LIMS IIS performance counters"
### 2. Automated Health Checks
**Daily health check automation:**
$healthCheckScript = @"
Import-Module WebAdministration
`$siteName = "
`$appPoolName = "
`$baseUrl = "
`$alertEmail = "
`$smtpServer = "
function Send-Alert {
param([string]$Subject, [string]
$Body)
Send-MailMessage -To $alertEmail -From "lims-monitor@company.com" -Subject
$Subject -Body $Body -SmtpServer
$smtpServer
}
$appPool = Get-IISAppPool -Name
$appPoolName
if(`$appPool.State -ne 'Started') {
Send-Alert "LIMS Alert: Application Pool Stopped" "Application pool $appPoolName is not running. State:
$(`$appPool.State)"
}
$website = Get-Website -Name
$siteName
if(`$website.State -ne 'Started') {
Send-Alert "LIMS Alert: Website Stopped" "Website $siteName is not running. State:
$(`$website.State)"
}
try {
$response = Invoke-WebRequest -Uri
$baseUrl -TimeoutSec 30 -UseBasicParsing
if(`$response.StatusCode -ne 200) {
Send-Alert "LIMS Alert: Web Connectivity Issue" "LIMS website returned HTTP $(
$response.StatusCode)"
}
} catch {
Send-Alert "LIMS Alert: Web Connectivity Failed" "Cannot connect to LIMS website: $(
$_.Exception.Message)"
}
`$recentErrors = Get-WinEvent -FilterHashtable @{
LogName='Application'
StartTime=(Get-Date).AddMinutes(-30)
Level=2
} -MaxEvents 1 -ErrorAction SilentlyContinue |
Where-Object {`$_.ProviderName -match 'IIS|ASP.NET|W3SVC'}
if(`$recentErrors) {
Send-Alert "LIMS Alert: Application Errors Detected" "Recent application errors detected in event log"
}
"@
$healthCheckScript | Out-File "C:\scripts\LIMS-Health-Check.ps1"
$action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-File C:\scripts\LIMS-Health-Check.ps1"
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 15) -RepetitionDuration (New-TimeSpan -Days 365)
Register-ScheduledTask -TaskName "LIMS Health Check" -Action $action -Trigger $trigger -Description "Automated LIMS health monitoring with alerts"
### 3. Log Management and Cleanup
**Automated log cleanup for LIMS environments:**
$logCleanupScript = @"
`$retentionDays = 30
$cutoffDate = (Get-Date).AddDays(-
$retentionDays)
$iisLogPath = "
$env:SystemDrive\inetpub\logs\LogFiles"
if(Test-Path `$iisLogPath) {
Get-ChildItem `$iisLogPath -Recurse -File |
Where-Object {$_.LastWriteTime -lt
$cutoffDate} |
Remove-Item -Force
Write-Output "Cleaned up IIS logs older than `$retentionDays days"
}
$httpErrPath = "
$env:SystemRoot\System32\LogFiles\HTTPERR"
if(Test-Path `$httpErrPath) {
Get-ChildItem `$httpErrPath -File |
Where-Object {$_.LastWriteTime -lt
$cutoffDate} |
Remove-Item -Force
Write-Output "Cleaned up HTTPERR logs older than `$retentionDays days"
}
`$appLogPath = "F:\LIMS\Logs"
if(Test-Path `$appLogPath) {
Get-ChildItem `$appLogPath -Recurse -File |
Where-Object {$_.LastWriteTime -lt
$cutoffDate -and `$_.Extension -eq '.log'} |
Remove-Item -Force
Write-Output "Cleaned up application logs older than `$retentionDays days"
}
"@
$logCleanupScript | Out-File "C:\scripts\LIMS-Log-Cleanup.ps1"
$action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-File C:\scripts\LIMS-Log-Cleanup.ps1"
$trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Sunday -At "02:00AM"
Register-ScheduledTask -TaskName "LIMS Log Cleanup" -Action $action -Trigger $trigger -Description "Weekly cleanup of LIMS and IIS log files"
---
## Quick Reference Commands
### Emergency Commands
iisreset /restart
Restart-WebAppPool -Name "
Stop-Website -Name "
Start-Website -Name "
Get-IISAppPool | Where-Object {$_.State -ne "Started"}
Get-Website | Where-Object {$_.State -ne "Started"}
Get-Process w3wp | Select-Object Id, ProcessName, StartTime, WorkingSet64
Get-WinEvent -FilterHashtable @{LogName='Application'; Level=2; StartTime=(Get-Date).AddHours(-1)} |
Where-Object {$_.ProviderName -match 'IIS|ASP.NET|W3SVC'} |
Select-Object TimeCreated, Id, LevelDisplayName, Message
### Discovery One-Liners
Get-Website | ForEach-Object { $_.Bindings.Collection | Select-Object @{n='Site';e={$_.Name}}, protocol, bindingInformation }
Get-Website | Where-Object {$_.PhysicalPath -like "F:\*"}
Get-Website | ForEach-Object { "$($_.logFile.Directory -replace '%SystemDrive%', $env:SystemDrive)\W3SVC$($_.id)" }
Get-ChildItem IIS:\SslBindings | ForEach-Object { Get-ChildItem Cert:\LocalMachine\My | Where-Object {$_.Thumbprint -eq $_.Thumbprint -and $_.NotAfter -lt (Get-Date).AddDays(30)} }
This comprehensive guide provides complete discovery, analysis, and debugging capabilities for IIS troubleshooting in LIMS environments, with emphasis on PowerShell automation and structured problem-solving approaches. All placeholders use the `<PLACEHOLDER_NAME>` format as specified.