Reorganize software catalog
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$Archive,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$Slug,
|
||||
|
||||
[string]$RootDirectory = "C:\codex\catalog-screenshots",
|
||||
|
||||
[string]$InitialKeys = "",
|
||||
|
||||
[ValidateRange(1, 60)]
|
||||
[int]$WaitSeconds = 8
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new()
|
||||
$workDirectory = Join-Path $RootDirectory "work\$Slug"
|
||||
$outputDirectory = Join-Path $RootDirectory "results"
|
||||
$runner = Join-Path $PSScriptRoot "runScreenshotTask.ps1"
|
||||
$javaExecutable = "C:\codex\jre\bin\javaw.exe"
|
||||
|
||||
function Get-NormalizedName {
|
||||
param([string]$Value)
|
||||
return ($Value.ToLowerInvariant() -replace '[^a-z0-9]', '')
|
||||
}
|
||||
|
||||
function Get-CandidateScore {
|
||||
param(
|
||||
[System.IO.FileInfo]$File,
|
||||
[string]$ProgramSlug
|
||||
)
|
||||
|
||||
$stem = Get-NormalizedName $File.BaseName
|
||||
$slugName = Get-NormalizedName $ProgramSlug
|
||||
$score = [Math]::Log([Math]::Max($File.Length, 1), 2)
|
||||
|
||||
if ($stem -eq $slugName) {
|
||||
$score += 100
|
||||
}
|
||||
foreach ($token in ($ProgramSlug -split '[-_]')) {
|
||||
if ($token.Length -ge 3 -and $stem.Contains((Get-NormalizedName $token))) {
|
||||
$score += 15
|
||||
}
|
||||
}
|
||||
|
||||
$relativePath = $File.FullName.Substring($workDirectory.Length).TrimStart('\')
|
||||
$score -= ([regex]::Matches($relativePath, '\\').Count * 2)
|
||||
|
||||
if ($File.BaseName -match '^(unins|uninstall|unwise|remove|register|regsvr)') {
|
||||
$score -= 200
|
||||
}
|
||||
if ($File.BaseName -match '(setup|install|autorun|update|updater)') {
|
||||
$score -= 50
|
||||
}
|
||||
|
||||
return $score
|
||||
}
|
||||
|
||||
function Stop-WorkDirectoryProcesses {
|
||||
$directoryPrefix = $workDirectory.TrimEnd('\') + '\'
|
||||
|
||||
for ($attempt = 0; $attempt -lt 3; $attempt++) {
|
||||
foreach ($item in Get-CimInstance Win32_Process -ErrorAction SilentlyContinue) {
|
||||
if ($item.ExecutablePath -and $item.ExecutablePath.StartsWith($directoryPrefix, [System.StringComparison]::OrdinalIgnoreCase)) {
|
||||
taskkill.exe /PID $item.ProcessId /T /F 2>$null | Out-Null
|
||||
}
|
||||
}
|
||||
Start-Sleep -Milliseconds 300
|
||||
}
|
||||
}
|
||||
|
||||
New-Item -ItemType Directory -Force -Path $workDirectory, $outputDirectory | Out-Null
|
||||
|
||||
try {
|
||||
Expand-Archive -LiteralPath $Archive -DestinationPath $workDirectory -Force
|
||||
|
||||
$candidates = @(
|
||||
Get-ChildItem -LiteralPath $workDirectory -Recurse -File -Filter "*.exe" |
|
||||
ForEach-Object {
|
||||
[pscustomobject]@{
|
||||
File = $_
|
||||
Score = Get-CandidateScore -File $_ -ProgramSlug $Slug
|
||||
}
|
||||
} |
|
||||
Sort-Object @{ Expression = "Score"; Descending = $true }, @{ Expression = { $_.File.Length }; Descending = $true }
|
||||
)
|
||||
|
||||
$arguments = ""
|
||||
$executable = $null
|
||||
$workingDirectory = $null
|
||||
if ($candidates.Count -gt 0) {
|
||||
$selected = $candidates[0].File
|
||||
$executable = $selected.FullName
|
||||
$workingDirectory = $selected.DirectoryName
|
||||
}
|
||||
else {
|
||||
$candidates = @(
|
||||
Get-ChildItem -LiteralPath $workDirectory -Recurse -File -Filter "*.jar" |
|
||||
Where-Object { $_.DirectoryName -notmatch '\\lib($|\\)' } |
|
||||
ForEach-Object {
|
||||
[pscustomobject]@{
|
||||
File = $_
|
||||
Score = Get-CandidateScore -File $_ -ProgramSlug $Slug
|
||||
}
|
||||
} |
|
||||
Sort-Object @{ Expression = "Score"; Descending = $true }, @{ Expression = { $_.File.Length }; Descending = $true }
|
||||
)
|
||||
if ($candidates.Count -eq 0 -or -not (Test-Path -LiteralPath $javaExecutable)) {
|
||||
[pscustomobject]@{
|
||||
success = $false
|
||||
reason = "no-executable"
|
||||
candidates = @()
|
||||
} | ConvertTo-Json -Depth 5 -Compress
|
||||
exit 1
|
||||
}
|
||||
$selected = $candidates[0].File
|
||||
$executable = $javaExecutable
|
||||
$workingDirectory = $selected.DirectoryName
|
||||
$arguments = "-jar `"$($selected.FullName)`""
|
||||
}
|
||||
|
||||
$installer = $selected.Extension -ieq ".exe" -and $selected.BaseName -match '(setup|install|autorun)'
|
||||
if ($installer) {
|
||||
[pscustomobject]@{
|
||||
success = $false
|
||||
reason = "installer-only"
|
||||
selected = $selected.FullName.Substring($workDirectory.Length).TrimStart('\')
|
||||
installer = $true
|
||||
candidates = @($candidates | Select-Object -First 10 | ForEach-Object {
|
||||
[pscustomobject]@{
|
||||
path = $_.File.FullName.Substring($workDirectory.Length).TrimStart('\')
|
||||
size = $_.File.Length
|
||||
score = [Math]::Round($_.Score, 2)
|
||||
}
|
||||
})
|
||||
} | ConvertTo-Json -Depth 5 -Compress
|
||||
exit 1
|
||||
}
|
||||
$winapp = "C:\codex\winapp\winapp.exe"
|
||||
$screenshotTool = if (Test-Path -LiteralPath $winapp) {
|
||||
$winapp
|
||||
}
|
||||
else {
|
||||
Join-Path $RootDirectory "nircmd.exe"
|
||||
}
|
||||
$runnerParameters = @{
|
||||
Executable = $executable
|
||||
Name = $Slug
|
||||
OutputDirectory = $outputDirectory
|
||||
WaitSeconds = $WaitSeconds
|
||||
Arguments = $arguments
|
||||
WorkingDirectory = $workingDirectory
|
||||
InitialKeys = $InitialKeys
|
||||
ScreenshotTool = $screenshotTool
|
||||
}
|
||||
$rawResult = & $runner @runnerParameters
|
||||
$result = $rawResult | ConvertFrom-Json
|
||||
|
||||
[pscustomobject]@{
|
||||
success = [bool]$result.success
|
||||
reason = $result.reason
|
||||
title = $result.title
|
||||
error = $result.error
|
||||
selected = $selected.FullName.Substring($workDirectory.Length).TrimStart('\')
|
||||
installer = $installer
|
||||
width = $result.width
|
||||
height = $result.height
|
||||
windows = $result.windows
|
||||
candidates = @($candidates | Select-Object -First 10 | ForEach-Object {
|
||||
[pscustomobject]@{
|
||||
path = $_.File.FullName.Substring($workDirectory.Length).TrimStart('\')
|
||||
size = $_.File.Length
|
||||
score = [Math]::Round($_.Score, 2)
|
||||
}
|
||||
})
|
||||
} | ConvertTo-Json -Depth 7 -Compress
|
||||
}
|
||||
catch {
|
||||
[pscustomobject]@{
|
||||
success = $false
|
||||
reason = "error"
|
||||
error = $_.Exception.Message
|
||||
candidates = @()
|
||||
} | ConvertTo-Json -Depth 5 -Compress
|
||||
exit 1
|
||||
}
|
||||
finally {
|
||||
Stop-WorkDirectoryProcesses
|
||||
Remove-Item -LiteralPath $workDirectory -Recurse -Force -ErrorAction SilentlyContinue
|
||||
Remove-Item -LiteralPath $Archive -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
Reference in New Issue
Block a user