MyITGuy
7/29/2025 - 2:34 PM

App Portal - Computer Name Detection Method Report

Requirements

  • Open relay mail server

How to use

  1. Create a directory named C:\Scripts\App Portal - Computer Name Detection Method Report on the Flexera App Portal server.
  2. Place all 4 files in the C:\Scripts\App Portal - Computer Name Detection Method Report directory. (App Portal - Computer Name Detection Method Report.ps1, run.cmd, App Portal - Computer Name Detection Method Report.xml, create_st.cmd)
  3. Edit App Portal - Computer Name Detection Method Report.ps1. Update variables which are defined above the ## DO NOT EDIT BELOW THIS LINE ## line.
  4. Test using run.cmd (check email to make sure it looks as expected)
  5. If testing is successful, us create_st.cmd to create and run as a Scheduled Task.
$smtpFromAddress = ""
$smtpToAddresses = @(
    ''
)
$SmtpServer = "smtp"

## DO NOT EDIT BELOW THIS LINE ##

$ReportName = "App Portal - Computer Name Detection Method Report"

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

function Main {
    if (!$Path) {
        $Path = Get-ChildItem -Path "$env:SystemDrive\inetpub\logs\LogFiles\W3SVC1\*.log" | Select-Object -Last 1 -Skip 1
    }

    $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 @('')) { return } # do not include entries for monitoring server ips
        if ($Entry.'c-ip' -in @('127.0.0.1')) { return } # do not include entries for localhost
        if ($Entry.'cs-username' -in @('')) { return } # do not include entries for testers

        $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
}

$HTMLHead = @'
<style type="text/css">
	BODY{
		background-color: #D8E9E8;
		font-family: verdana;
		color: #1A64A1;
		font-size: 8pt;
		cell-padding: 2pt;
	}
	TABLE{
		font-size: 11px;
		border-width: 1px;
		border-style: solid;
		border-color: #D6D6D6;
		border-collapse: collapse;
		border-spacing: 10px;
	}
	TH{
		font-size: 18px;
		color: white;
		border-width: 1px;
		padding: 4px;
		border-style: solid;
		border-color: #D6D6D6;
		background-color: #1A64A1;
	}
	TD{
		color: #1A64A1;
		border-width: 1px;
		padding: 4px;
		border-style: solid;
		border-color: #D6D6D6;
		background-color: white;
	}
</style>
'@

$HTMLPreContent = @"
This report runs as a scheduled task, once a day at 7 AM, from $($env:COMPUTERNAME).

<h1>$ReportName</h1>
"@

$JobDetail = Main

$JobDetailCount = $JobDetail | Where-Object { [System.String]::IsNullOrEmpty($_.'ap-method') -eq $false } | Measure-Object | Select-Object -ExpandProperty Count

$JobDetail_HTMLFragment = $JobDetail | ConvertTo-HTML -Fragment -PreContent "<h2>Results [$($JobDetailCount)]</h2>" | Out-String

$HTMLBody = ConvertTo-Html -Head $HTMLHead -PreContent $HTMLPreContent -PostContent $JobDetail_HTMLFragment | Out-String

$IADsObject = ([adsisearcher]"(&(objectclass=group)(proxyAddresses=smtp:$($smtpFromAddress)))").FindOne()
$smtpFrom = "$($IADsObject.Properties.name[0]) <$($smtpFromAddress)>"

$MailMessage_Splat = @{
    From = $smtpFrom
    To = @()
    BodyAsHtml = $true
    Body = $HTMLBody
    SmtpServer = $SmtpServer
    Subject = $ReportName
}

foreach ($SendTo In $smtpToAddresses) {
	$IADsObject = ([adsisearcher]"(&(!userAccountControl:1.2.840.113556.1.4.803:=2)(proxyAddresses=smtp:$($SendTo)))").FindOne()
	if ( $IADsObject.Count -eq 1 ) {
		$MailMessage_Splat.To += "$($IADsObject.Properties.name[0]) <$($SendTo)>"
		Write-Host "Sending to '$SendTo'."
	} else {
		Write-Host "Not sending to '$SendTo'. User not found." -ForegroundColor Yellow
	}
}

Send-MailMessage @MailMessage_Splat
@echo off
pushd "%~dp0"
powershell.exe -executionpolicy bypass -file "App Portal - Computer Name Detection Method Report.ps1"
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <RegistrationInfo>
    <Date>2020-05-08T08:33:52.7776725</Date>
    <URI>\App Portal - Computer Name Detection Method Report</URI>
  </RegistrationInfo>
  <Triggers>
    <CalendarTrigger>
      <StartBoundary>2025-07-01T07:00:00</StartBoundary>
      <Enabled>true</Enabled>
      <ScheduleByDay>
        <DaysInterval>1</DaysInterval>
      </ScheduleByDay>
    </CalendarTrigger>
  </Triggers>
  <Principals>
    <Principal id="Author">
      <UserId>S-1-5-18</UserId>
      <RunLevel>HighestAvailable</RunLevel>
    </Principal>
  </Principals>
  <Settings>
    <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
    <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
    <AllowHardTerminate>true</AllowHardTerminate>
    <StartWhenAvailable>false</StartWhenAvailable>
    <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
    <IdleSettings>
      <StopOnIdleEnd>true</StopOnIdleEnd>
      <RestartOnIdle>false</RestartOnIdle>
    </IdleSettings>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>false</Hidden>
    <RunOnlyIfIdle>false</RunOnlyIfIdle>
    <WakeToRun>false</WakeToRun>
    <ExecutionTimeLimit>PT72H</ExecutionTimeLimit>
    <Priority>7</Priority>
  </Settings>
  <Actions Context="Author">
    <Exec>
      <Command>"C:\Scripts\App Portal - Computer Name Detection Method Report\run.cmd"</Command>
    </Exec>
  </Actions>
</Task>
@echo off
pushd "%~dp0"
schtasks.exe /Create /XML "App Portal - Computer Name Detection Method Report.xml" /TN "App Portal - Computer Name Detection Method Report"