This document provides every possible PowerShell command for the Discovery phase.
It focuses on one website at a time, using [SITE_NAME] to specify the website.
It assumes no prior knowledge of the setup (no site names, paths, or hostnames).
It clarifies how to map a website to its site ID (e.g., ID 1 maps to W3SVC1
log folder).
It retrieves the most recent log file for the website as [LOG_FILE].
Commands cover the website’s settings, log directory, log file, API paths (e.g., /api/
requests, web apps, URL patterns), bindings, application pool, and server-level details (services, features, network diagnostics).
Placeholders are marked in square brackets (e.g., [SITE_NAME]).
Each placeholder has a preceding command to retrieve its value.
Commands use literal values where possible and handle errors for missing features.
Commands and descriptions are separated by blank lines for readability.
Run all commands in PowerShell as Administrator to access IIS configurations.
Get-WindowsFeature -Name Web* | Select-Object Name, DisplayName, Installed, Description, DependsOn | Sort-Object Name | Format-Table -AutoSize
What it does:
Lists all web server components (e.g., core IIS, management tools, FTP).
Shows installation status, descriptions, and dependencies.
Helps confirm if IIS and related features are installed.
Get-Service | Where-Object { $_.Name -like '*W3SVC*' -or $_.Name -like '*IIS*' -or $_.Name -like '*WAS*' -or $_.Name -like '*HTTP*' -or $_.Name -like '*MSFTPSVC*' -or $_.Name -like '*SMTPSVC*' } | Select-Object Name, DisplayName, Status, StartType, DependentServices | Format-Table -AutoSize
What it does:
Lists services related to the web server, FTP, or email (SMTP).
Shows service name, display name, status, startup type, and dependencies.
Helps verify if IIS-related services are running.
Get-Website | Select-Object Name, ID, @{Name='LogDirectory';Expression={$_.LogFile.Directory + '\W3SVC' + $_.ID}}, State, PhysicalPath, EnabledProtocols, @{Name='Bindings';Expression={$_.Bindings.Collection | ForEach-Object { $_.Protocol + '://' + $_.BindingInformation }}} | Format-Table -AutoSize
What it does:
Lists every website’s name, ID (e.g., 1 maps to W3SVC1
), log directory, status, folder path, protocols, and bindings.
Use to choose a website name for [SITE_NAME].
Shows the W3SVC[ID]
log folder for each website.
Placeholder: [SITE_NAME] (e.g., "Default Web Site").
Get-Website | Select-Object -ExpandProperty Name | Select-Object -First 1
What it does:
Gets the name of one website (e.g., "Default Web Site").
Use as [SITE_NAME] in later commands.
Picks the first website if multiple exist.
Get-Website | Where-Object { $_.Name -eq '[SITE_NAME]' } | Select-Object -ExpandProperty ID
What it does:
Gets the site ID (e.g., 1 for W3SVC1
) for the website named [SITE_NAME].
Replace [SITE_NAME] with the name from the previous command.
Identifies the W3SVC[ID]
log folder for the website.
Placeholder: [SITE_NAME] (e.g., "Default Web Site").
Get-Website | Where-Object { $_.Name -eq '[SITE_NAME]' } | Select-Object @{Name='LogDirectory';Expression={$_.LogFile.Directory + '\W3SVC' + $_.ID}}
What it does:
Gets the log directory for the website named [SITE_NAME].
Replace [SITE_NAME] with the name from the website name command.
Returns the path (e.g., C:\inetpub\logs\LogFiles\W3SVC1
).
Placeholder: [SITE_NAME] (e.g., "Default Web Site").
Get-ChildItem -Path (Get-Website | Where-Object { $_.Name -eq '[SITE_NAME]' } | Select-Object -ExpandProperty LogFile.Directory)\W3SVC*(Get-Website | Where-Object { $_.Name -eq '[SITE_NAME]' } | Select-Object -ExpandProperty ID) -Include *.log -ErrorAction SilentlyContinue | Sort-Object LastWriteTime -Descending | Select-Object -First 1 | Select-Object @{Name='LogFile';Expression={$_.FullName}}, LastWriteTime | Format-Table -AutoSize
What it does:
Gets the most recent log file for the website named [SITE_NAME].
Replace [SITE_NAME] with the name from the website name command.
Returns the file path (e.g., C:\inetpub\logs\LogFiles\W3SVC1\u_ex251103.log
) as [LOG_FILE].
Placeholder: [SITE_NAME] (e.g., "Default Web Site").
Get-Content -Path '[LOG_FILE]' -Tail 100 -ErrorAction SilentlyContinue | Format-Table -AutoSize
What it does:
Shows the last 100 lines from [LOG_FILE].
Replace [LOG_FILE] with the path from the most recent log file command.
Includes request details like URLs, IP addresses, and status codes.
Placeholder: [LOG_FILE] (e.g., C:\inetpub\logs\LogFiles\W3SVC1\u_ex251103.log
).
Get-Content -Path '[LOG_FILE]' -ErrorAction SilentlyContinue | Select-String -Pattern '/api/' | Select-Object LineNumber, Line | Format-Table -AutoSize
What it does:
Searches [LOG_FILE] for requests containing “/api/”.
Replace [LOG_FILE] with the path from the most recent log file command.
Shows line numbers and request details to identify API activity.
Placeholder: [LOG_FILE] (e.g., C:\inetpub\logs\LogFiles\W3SVC1\u_ex251103.log
).
Get-WebApplication -Site '[SITE_NAME]' | Select-Object Path, PhysicalPath, ApplicationPool, EnabledProtocols, @{Name='VirtualDirectories';Expression={(Get-WebVirtualDirectory -Application $_.Path -Site '[SITE_NAME]' -ErrorAction SilentlyContinue).Path}} | Format-Table -AutoSize
What it does:
Lists web applications and subfolders for the website named [SITE_NAME].
Replace [SITE_NAME] with the name from the website name command.
Includes URL paths (e.g., /api
) that may be API endpoints.
Shows physical paths, app pools, protocols, and virtual directories.
Placeholder: [SITE_NAME] (e.g., "Default Web Site").
Get-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' -Filter "system.webServer/rewrite/rules" -Location "[SITE_NAME]" -Name * -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Rules | Where-Object { $_.Pattern -like '*api*' } | Select-Object Name, Pattern, @{Name='ActionUrl';Expression={$_.Action.Url}} | Format-Table -AutoSize
What it does:
Lists URL rewrite rules containing “api” for the website named [SITE_NAME].
Replace [SITE_NAME] with the name from the website name command.
Runs only if the URL Rewrite module is installed.
Shows rule names, patterns, and redirected URLs.
Placeholder: [SITE_NAME] (e.g., "Default Web Site").
Get-WebConfiguration -Filter 'system.applicationHost/sites/site' | Where-Object { $_.Name -eq '[SITE_NAME]' } | Select-Object @{Name='SiteName';Expression={$_.Name}}, @{Name='DefaultDocument';Expression={$_.GetChildElement('defaultDocument').Enabled}}, @{Name='DirectoryBrowsing';Expression={$_.GetChildElement('directoryBrowse').Enabled}}, @{Name='Compression';Expression={$_.GetChildElement('httpCompression').Enabled}} | Format-Table -AutoSize
What it does:
Shows configuration settings for the website named [SITE_NAME].
Replace [SITE_NAME] with the name from the website name command.
Includes default document, directory browsing, and compression settings.
Placeholder: [SITE_NAME] (e.g., "Default Web Site").
Get-Website | Where-Object { $_.Name -eq '[SITE_NAME]' } | Select-Object -ExpandProperty ApplicationPool
What it does:
Gets the application pool name for the website named [SITE_NAME].
Replace [SITE_NAME] with the name from the website name command.
Returns the name to use as [APP_POOL_NAME].
Placeholder: [SITE_NAME] (e.g., "Default Web Site").
Get-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' -Filter "system.applicationHost/applicationPools/add[@name='[APP_POOL_NAME]']" -Name * | Select-Object Name, ManagedPipelineMode, ManagedRuntimeVersion, @{Name='RecyclingSchedule';Expression={$_.Recycling.PeriodicRestart.Schedule.Collection}} | Format-Table -AutoSize
What it does:
Shows settings for the application pool named [APP_POOL_NAME].
Replace [APP_POOL_NAME] with the name from the previous command.
Includes processing mode, .NET version, and recycling schedule.
Placeholder: [APP_POOL_NAME] (e.g., "DefaultAppPool").
Get-WebBinding -Name '[SITE_NAME]' | Where-Object { $_.Protocol -eq 'https' } | Select-Object @{Name='SiteName';Expression={$_.GetParentElement().Name}}, @{Name='Binding';Expression={$_.BindingInformation}}, CertificateHash, @{Name='CertificateDetails';Expression={(Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object { $_.Thumbprint -eq $_.CertificateHash } | Select-Object Subject, NotAfter, Issuer)}} | Format-Table -AutoSize
What it does:
Lists SSL certificate details for the website named [SITE_NAME].
Replace [SITE_NAME] with the name from the website name command.
Shows certificate hash, subject, expiration, and issuer for HTTPS bindings.
Placeholder: [SITE_NAME] (e.g., "Default Web Site").
Get-WebBinding -Name '[SITE_NAME]' | ForEach-Object { $hostName = ($_.BindingInformation -split ':')[1]; if ($hostName -and $hostName -ne '*') { $hostName } }
What it does:
Gets the hostname (e.g., www.example.com) for the website named [SITE_NAME].
Replace [SITE_NAME] with the name from the website name command.
Returns the hostname to use as [HOSTNAME].
Placeholder: [SITE_NAME] (e.g., "Default Web Site").
Test-Connection -ComputerName '[HOSTNAME]' -Count 2 -ErrorAction SilentlyContinue | Select-Object Address, ResponseTime, Status | Format-Table -AutoSize
What it does:
Pings the hostname [HOSTNAME].
Replace [HOSTNAME] with the hostname from the previous command.
Checks network reachability and response time.
Placeholder: [HOSTNAME] (e.g., www.example.com).
tracert -h 10 '[HOSTNAME]'
What it does:
Runs a traceroute to [HOSTNAME].
Replace [HOSTNAME] with the hostname from the hostname command.
Shows the network path to the hostname.
Placeholder: [HOSTNAME] (e.g., www.example.com).
Get-WebBinding -Name '[SITE_NAME]' | ForEach-Object { $port = ($_.BindingInformation -split ':')[2]; $hostName = ($_.BindingInformation -split ':')[1]; if ($port -and ($port -eq '80' -or $port -eq '443')) { Test-NetConnection -ComputerName ($hostName -eq '*' ? 'localhost' : $hostName) -Port $port -ErrorAction SilentlyContinue | Select-Object ComputerName, RemotePort, TcpTestSucceeded } } | Format-Table -AutoSize
What it does:
Tests ports (80 for HTTP, 443 for HTTPS) for the website named [SITE_NAME].
Replace [SITE_NAME] with the name from the website name command.
Checks if the ports are open and reachable.
Placeholder: [SITE_NAME] (e.g., "Default Web Site").
Resolve-DnsName -Name '[HOSTNAME]' -ErrorAction SilentlyContinue | Select-Object Name, Type, Address | Format-Table -AutoSize
What it does:
Looks up DNS records for [HOSTNAME].
Replace [HOSTNAME] with the hostname from the hostname command.
Shows IP addresses and DNS record types.
Placeholder: [HOSTNAME] (e.g., www.example.com).
Get-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' -Filter 'system.webServer/tracing/traceFailedRequests' -Location '[SITE_NAME]' -Name * -ErrorAction SilentlyContinue | Select-Object @{Name='Enabled';Expression={$_.Enabled}}, @{Name='TraceDirectory';Expression={$_.Directory}} | Format-Table -AutoSize
What it does:
Checks if failed request logging is enabled for the website named [SITE_NAME].
Replace [SITE_NAME] with the name from the website name command.
Shows the trace directory if enabled.
Placeholder: [SITE_NAME] (e.g., "Default Web Site").
Get-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' -Filter 'system.webServer/tracing/traceFailedRequests' -Name * -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Directory
What it does:
Gets the folder for failed request logs.
Returns the path to use as [TRACE_DIRECTORY].
Typically returns a path like C:\inetpub\logs\FailedReqLogFiles
.
Get-ChildItem -Path '[TRACE_DIRECTORY]' -Recurse -Include *.fr* -ErrorAction SilentlyContinue | Select-Object FullName, LastWriteTime, Length | Format-Table -AutoSize
What it does:
Lists all failed request log files in [TRACE_DIRECTORY].
Replace [TRACE_DIRECTORY] with the path from the previous command.
Shows file paths, modification times, and sizes.
Placeholder: [TRACE_DIRECTORY] (e.g., C:\inetpub\logs\FailedReqLogFiles
).
Start-Transcript -Path 'C:\Troubleshooting\IIS_Discovery_Log.txt' -Append
What it does:
Starts logging all commands and their output to a file.
Run before other commands.
Stop logging with Stop-Transcript
.