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