AppLocate.psm1
|
# PowerShell module wrapper for applocate # Exposes: Invoke-AppLocate, Find-App, Get-AppLocateJson # PSScriptAnalyzer: PSAvoidAssignmentToAutomaticVariable warnings were reported referencing lines with no $args assignments. # Suppressing rule at file scope as we only *read* remaining arguments via a custom parameter array. [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidAssignmentToAutomaticVariable','')] $script:ApplocatePath = $null function Set-AppLocatePath { <# .SYNOPSIS Sets the path to the applocate executable. .DESCRIPTION Configures the module to use a specific applocate.exe path. Use this if the executable is not in the module directory or artifacts folder. .PARAMETER Path Full path to applocate.exe .EXAMPLE Set-AppLocatePath "C:\tools\applocate.exe" #> param([string]$Path) if(-not (Test-Path $Path)) { throw "Path not found: $Path" } $script:ApplocatePath = (Resolve-Path $Path).Path } function Get-AppLocatePath { <# .SYNOPSIS Returns the path to the applocate executable. .DESCRIPTION Returns the configured path, or auto-discovers it from: 1. Module directory (bundled with PSGallery package) 2. artifacts/win-x64 (development layout) 3. System PATH #> if(-not $script:ApplocatePath) { $moduleRoot = Split-Path -Parent $PSCommandPath # 1. Check module directory (PSGallery bundle) $candidate = Join-Path $moduleRoot 'applocate.exe' if(Test-Path $candidate){ $script:ApplocatePath = (Resolve-Path $candidate).Path return $script:ApplocatePath } # 2. Check artifacts/win-x64 (development layout) $candidate = Join-Path $moduleRoot 'artifacts/win-x64/applocate.exe' if(Test-Path $candidate){ $script:ApplocatePath = (Resolve-Path $candidate).Path return $script:ApplocatePath } # 3. Check system PATH $inPath = Get-Command 'applocate' -ErrorAction SilentlyContinue if($inPath){ $script:ApplocatePath = $inPath.Source return $script:ApplocatePath } } if(-not $script:ApplocatePath) { throw "applocate executable not found. Install via WinGet (winget install AppLocate.AppLocate), download from GitHub releases, or use Set-AppLocatePath." } return $script:ApplocatePath } function Invoke-AppLocate { <# .SYNOPSIS Invokes the applocate CLI with the specified query and options. .DESCRIPTION Runs applocate.exe with any combination of arguments. Use -Json or -Csv to get structured output, or pass CLI flags directly. .PARAMETER QueryAndOptions The application query and any additional CLI options (e.g., --all, --evidence) .PARAMETER Json Output results as JSON .PARAMETER Csv Output results as CSV .EXAMPLE Invoke-AppLocate "chrome" .EXAMPLE Invoke-AppLocate "vscode" "--all" "--evidence" -Json .EXAMPLE Invoke-AppLocate "node" "--running" "--exe" #> [CmdletBinding()] param( [Parameter(Mandatory, Position=0, ValueFromRemainingArguments)] [string[]]$QueryAndOptions, [switch]$Json, [switch]$Csv ) $exe = Get-AppLocatePath $cliArgs = @() if($Json){ $cliArgs += '--json' } elseif($Csv){ $cliArgs += '--csv' } $cliArgs += $QueryAndOptions # Build a properly escaped argument string for ProcessStartInfo $argString = ($cliArgs | ForEach-Object { if ($_ -match '\s') { "`"$_`"" } else { $_ } }) -join ' ' $psi = New-Object System.Diagnostics.ProcessStartInfo -Property @{ FileName = $exe; Arguments = $argString; RedirectStandardOutput = $true; RedirectStandardError = $true; UseShellExecute = $false } $p = [System.Diagnostics.Process]::Start($psi) $out = $p.StandardOutput.ReadToEnd() $p.WaitForExit() if($p.ExitCode -ne 0 -and $p.ExitCode -ne 1){ Write-Error "applocate exited $($p.ExitCode)" } return $out } function Get-AppLocateJson { <# .SYNOPSIS Searches for an application and returns results as PowerShell objects. .DESCRIPTION Queries applocate with JSON output and parses the result into PowerShell objects. Supports filtering by confidence threshold and result limit. .PARAMETER Query The application name or alias to search for .PARAMETER ConfidenceMin Minimum confidence score (0-1) to include in results .PARAMETER Limit Maximum number of results to return .EXAMPLE Get-AppLocateJson -Query "code" .EXAMPLE Get-AppLocateJson -Query "chrome" -ConfidenceMin 0.7 -Limit 5 .OUTPUTS PSCustomObject[] - Array of application hit objects with path, confidence, type, etc. #> [CmdletBinding()] param( [Parameter(Mandatory)][string]$Query, [double]$ConfidenceMin, [int]$Limit ) $cliArgs = @($Query,'--json') if($PSBoundParameters.ContainsKey('ConfidenceMin')){ $cliArgs += @('--confidence-min', $ConfidenceMin) } if($PSBoundParameters.ContainsKey('Limit')){ $cliArgs += @('--limit', $Limit) } $raw = Invoke-AppLocate -QueryAndOptions $cliArgs -Json try { return $raw | ConvertFrom-Json } catch { Write-Error "Failed to parse JSON: $_"; return $raw } } function Find-App { <# .SYNOPSIS Quick search for an application (alias for Get-AppLocateJson). .DESCRIPTION Convenience function that wraps Get-AppLocateJson for simple queries. .PARAMETER Query The application name or alias to search for .EXAMPLE Find-App "notepad" .EXAMPLE Find-App "git" | Select-Object path, confidence #> [CmdletBinding()] param( [Parameter(Mandatory)][string]$Query ) Get-AppLocateJson -Query $Query } Export-ModuleMember -Function Set-AppLocatePath,Get-AppLocatePath,Invoke-AppLocate,Get-AppLocateJson,Find-App |