Skip to content

IIS Log Management PowerShell Scripts

Category: IIS Log Management Tags: IIS, PowerShell, Logging, Windows, Monitoring, Scripts

Overview

Each function can be used independently, but some call others as noted below.

Log File Location Functions

Get IIS Log File Locations

function Get-IISLogPaths {
    Import-Module WebAdministration
    Get-Website | ForEach-Object {
        $logPath = (Get-ItemProperty "IIS:\Sites\$($_.Name)" -Name logFile.directory).Value
        $logPath = $logPath -replace '%SystemDrive%', $env:SystemDrive
        [PSCustomObject]@{
            SiteName = $_.Name
            LogPath = "$logPath\W3SVC$($_.ID)"
            Status = $_.State
        }
    }
}

Get Default Website Log Path

function Get-DefaultLogPath {
    return "C:\inetpub\logs\LogFiles\W3SVC1"
}

Log Parsing Functions

Parse W3C Log Files (requires log path)

function Parse-IISLogs {
    param(
        [Parameter(Mandatory=$true)]
        [string]$LogPath,  # Example: "C:\inetpub\logs\LogFiles\W3SVC1"
        [datetime]$StartDate = (Get-Date).AddDays(-1),
        [datetime]$EndDate = (Get-Date),
        [string]$StatusCode = "*"
    )

    Get-ChildItem "$LogPath\*.log" | Where-Object {
        $_.LastWriteTime -ge $StartDate -and $_.LastWriteTime -le $EndDate
    } | ForEach-Object {
        $content = Get-Content $_.FullName
        $fields = ($content | Where-Object { $_ -like "#Fields:*" } | Select-Object -First 1) -replace "#Fields: ", "" -split " "

        $content | Where-Object { 
            $_ -notlike "#*" -and $_ -ne "" 
        } | ForEach-Object {
            $values = $_ -split " "
            $logEntry = [ordered]@{}

            for ($i = 0; $i -lt $fields.Length; $i++) {
                $logEntry[$fields[$i]] = $values[$i]
            }

            if ($logEntry['sc-status'] -like $StatusCode) {
                [PSCustomObject]$logEntry
            }
        }
    }
}

Get Today's Logs from Default Location

function Get-TodaysLogs {
    $logPath = "C:\inetpub\logs\LogFiles\W3SVC1"
    $today = Get-Date -Format "yyMMdd"
    $logFile = Get-ChildItem "$logPath\ex$today.log" -ErrorAction SilentlyContinue

    if ($logFile) {
        Get-Content $logFile.FullName | Where-Object { $_ -notlike "#*" -and $_ -ne "" } | Select-Object -Last 20
    } else {
        Write-Host "No log file found for today at $logPath" -ForegroundColor Yellow
    }
}

Error Analysis Functions

Get Today's Error Logs (4xx, 5xx status codes)

function Get-IISErrors {
    param([string]$SiteName = "Default Web Site")

    $site = Get-Website -Name $SiteName
    $logPath = (Get-ItemProperty "IIS:\Sites\$SiteName" -Name logFile.directory).Value
    $logPath = $logPath -replace '%SystemDrive%', $env:SystemDrive
    $fullPath = "$logPath\W3SVC$($site.ID)"

    Parse-IISLogs -LogPath $fullPath -StatusCode "[45]*" | 
        Group-Object 'sc-status' | 
        Sort-Object Count -Descending |
        Select-Object Name, Count, @{Name='URLs'; Expression={($_.Group | Select-Object -First 5 'cs-uri-stem').('cs-uri-stem')}}
}

Real-Time Monitoring Functions

Monitor Real-Time IIS Logs

function Watch-IISLogs {
    param(
        [string]$SiteName = "Default Web Site",
        [int]$TailLines = 10
    )

    $site = Get-Website -Name $SiteName
    $logPath = (Get-ItemProperty "IIS:\Sites\$SiteName" -Name logFile.directory).Value
    $logPath = $logPath -replace '%SystemDrive%', $env:SystemDrive
    $logFile = Get-ChildItem "$logPath\W3SVC$($site.ID)" -Filter "*.log" | Sort-Object LastWriteTime -Descending | Select-Object -First 1

    Get-Content $logFile.FullName -Tail $TailLines -Wait
}

Configuration Functions

Configure W3C Logging Format

function Set-IISLogFormat {
    param(
        [string]$SiteName = "Default Web Site",
        [string[]]$Fields = @('date', 'time', 'c-ip', 'cs-username', 'cs-method', 'cs-uri-stem', 'cs-uri-query', 'sc-status', 'sc-bytes', 'cs-bytes', 'time-taken', 'cs(User-Agent)', 'cs(Referer)')
    )

    Import-Module WebAdministration
    Set-WebConfigurationProperty -Filter "system.webServer/httpLogging" -PSPath "IIS:\Sites\$SiteName" -Name "selectiveLogging" -Value "LogAll"

    # Set log fields
    $logFields = $Fields -join ','
    Set-WebConfigurationProperty -Filter "system.webServer/httpLogging" -PSPath "IIS:\Sites\$SiteName" -Name "logExtFileFlags" -Value $logFields
}

Analysis Functions

Analyze Top IPs and URLs

function Get-IISTopStats {
    param(
        [string]$SiteName = "Default Web Site",
        [int]$TopCount = 10
    )

    $site = Get-Website -Name $SiteName
    $logPath = (Get-ItemProperty "IIS:\Sites\$SiteName" -Name logFile.directory).Value
    $logPath = $logPath -replace '%SystemDrive%', $env:SystemDrive
    $fullPath = "$logPath\W3SVC$($site.ID)"

    $logs = Parse-IISLogs -LogPath $fullPath

    Write-Host "Top $TopCount IPs:" -ForegroundColor Green
    $logs | Group-Object 'c-ip' | Sort-Object Count -Descending | Select-Object -First $TopCount Name, Count

    Write-Host "`nTop $TopCount URLs:" -ForegroundColor Green
    $logs | Group-Object 'cs-uri-stem' | Sort-Object Count -Descending | Select-Object -First $TopCount Name, Count

    Write-Host "`nTop $TopCount User Agents:" -ForegroundColor Green
    $logs | Group-Object 'cs(User-Agent)' | Sort-Object Count -Descending | Select-Object -First $TopCount Name, Count
}

Usage Examples

Simple Commands

# Just see today's logs
Get-TodaysLogs

# Find log paths if you don't know where logs are
Get-IISLogPaths

Parse Specific Log Paths

# Parse logs from default location
Parse-IISLogs -LogPath "C:\inetpub\logs\LogFiles\W3SVC1"

# Parse logs from F drive
Parse-IISLogs -LogPath "F:\inetpub\logs\LogFiles\W3SVC1"

# Get only error logs (4xx status codes)
Parse-IISLogs -LogPath "C:\inetpub\logs\LogFiles\W3SVC1" -StatusCode "4*"

# Get only today's logs
Parse-IISLogs -LogPath "C:\inetpub\logs\LogFiles\W3SVC1" -StartDate (Get-Date).Date

Note: The path goes AFTER -LogPath and must be in quotes!