MyITGuy
6/26/2025 - 1:23 PM

Flexera App Portal Web Extension IIS Log Analyzer

function Get-FlexeraAppPortalNameResolution {
    [CmdletBinding()]
    param(
        [System.IO.FileInfo[]]$Path
        ,
        [string]$ClientIP
    )

    function ConvertFrom-IISLog {
        [CmdletBinding()]
        param(
            [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
            [string]$Path
            ,
            [switch]$ShowFields
        )
        process {
            foreach ($PathItem In $Path) {
                $Contents = Get-Content -Path $PathItem -Raw
                $FieldHeaders = (([regex]::Split($Contents, [string]'^#Fields:', "Multiline")[1] -split '\n')[0]).Trim() -split '\s+' | ForEach-Object { $_.Trim() }
                # $FieldHeaders = ($Contents | Select-String -Pattern '^#Fields:') -split '\s+' | Select-Object -Skip 1
                if ($ShowFields) {
                    $FieldHeaders
                    return
                }
                Import-Csv -Delimiter ' ' -Header $FieldHeaders -Path $PathItem | Where-Object { $_.date -notmatch '^#' } | ForEach-Object {
                    $Item = $_
                    foreach ($FieldHeader In $FieldHeaders) {
                        if ($Item.$FieldHeader -eq '-') {
                            $Item.$FieldHeader = $null
                        }
                    }
                    $Item | Add-Member -MemberType ScriptProperty -Name 'TimeCreated' -Value { ([System.DateTime]"$($this.date) $($this.time)").ToLocalTime() }
                    $Item
                }
            }
        }
    }

    filter filterByClientIP {
        $Object = $_
        if ($ClientIP) {
            $Object | Where-Object 'c-ip' -eq $ClientIP
        }
        else {
            $_
        }
    }

    $regexPattern = '(Processor|Loader)\.aspx'

    foreach ($LogFile In $Path) {
        Write-Verbose "Path: $($LogFile)"
        if ( ($Path | Select-String -Pattern $regexPattern).Count -eq 0 ) {
            Write-Warning "Log does not contain search criteria. ($($LogFile))"
            return
        }
        $LogFile | ConvertFrom-IISLog | Where-Object { $_.'cs-uri-stem' -match $regexPattern } | filterByClientIP
    }
}

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")

#region OpenFileDialog
$OpenFileDialog = [System.Windows.Forms.OpenFileDialog]@{
    InitialDirectory = "$env:SystemDrive\inetpub\logs\LogFiles\W3SVC1"
    CheckFileExists  = 1
    ValidateNames    = 1
    Multiselect      = 1
    Filter           = 'Log Files (*.log)|*.log|All Files (*.*)|*.*'
}
$OpenFileDialog.ShowDialog() | Out-Null
if (-not $OpenFileDialog.FileName) {
    Write-Host "File not found." -ForegroundColor Yellow
    return
}
$Path = $OpenFileDialog.FileNames
#endregion OpenFileDialog

$FlexeraAppPortalNameResolution = Get-FlexeraAppPortalNameResolution -Path $Path | Sort-Object -Property @{Expression = {[datetime]"$($_.date) $($_.time)"}; Ascending = $true}
$FlexeraAppPortalNameResolution | Add-Member -MemberType NoteProperty -Name 'ap-timetaken' -Value $null
$FlexeraAppPortalNameResolution | Add-Member -MemberType NoteProperty -Name 'ap-method' -Value $null

$FlexeraAppPortalNameResolution = $FlexeraAppPortalNameResolution | Select-Object -ExcludeProperty 'cs(User-Agent)' -Property * | Group-Object -Property 'c-ip' | ForEach-Object {
    $_.Group
}

$PreviousEntry = $null
$OutputObject = $FlexeraAppPortalNameResolution | ForEach-Object {
    $Entry = $_

    if ([System.String]::IsNullOrEmpty($Entry.'cs-username')) { return } # do not include entries with no user name
    if ($Entry.'c-ip' -in @('127.0.0.1')) { return } # do not include entries for localhost

    $Entry.'ap-method' = [regex]::Match([string]($Entry.'cs-uri-query'), '^d=(?<apmethod>\w+)&').Groups['apmethod'].Value
    if (($Entry.'cs-uri-query') -match '^d=' -and ([System.String]::IsNullOrEmpty($Entry.'ap-method'))) { $Entry.'ap-method' = 'blank' }
    if ($Entry.'cs-uri-stem' -match [regex]::Escape('Processor.aspx') -and ( $Entry.'cs-username' -eq $PreviousEntry.'cs-username' )) {
        $Entry.'ap-timetaken' = New-TimeSpan -Start ([datetime]"$($PreviousEntry.date) $($PreviousEntry.time)") -End ([datetime]"$($Entry.date) $($Entry.time)")
    }
    $PreviousEntry = $Entry
    $Entry
}

$OutputObject | Out-GridView -Title 'Flexera App Portal Web Extension IIS Log Analyzer'

if (($OutputObject | Measure-Object).Count -eq 0) {
    Write-Warning "Not IIS log entries found that meet the criteria."
}