IIS Discovery Phase: Commands for a Single Website

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.

Check if the Web Server Is Installed


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.

List All Services


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.

List All Websites to Choose [SITE_NAME]


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 a Website Name for [SITE_NAME]


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 the Site ID for [SITE_NAME]


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 the Log Directory for [SITE_NAME]


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 the Most Recent Log File for [SITE_NAME] as [LOG_FILE]


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").

View Recent Entries in [LOG_FILE]


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).

Search for API Requests in [LOG_FILE]


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).

List Web Applications for [SITE_NAME] (API Paths)


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").

List URL Rewrite Rules for [SITE_NAME] (API Patterns)


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").

List Settings for [SITE_NAME]


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 Application Pool for [SITE_NAME]


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").

List Settings for Application Pool [APP_POOL_NAME]


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").

Check SSL Certificates for [SITE_NAME]


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 Hostname for [SITE_NAME] as [HOSTNAME]


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").

Ping Hostname [HOSTNAME]


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).

Trace Network Route to [HOSTNAME]


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).

Test Web Ports for [SITE_NAME]


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 DNS for [HOSTNAME]


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).

Check Failed Request Logging for [SITE_NAME]


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 Failed Request Log Directory for [TRACE_DIRECTORY]


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.

List Failed Request Logs in [TRACE_DIRECTORY]


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).

Save All Output to a File


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.