# encoding: ascii
# api: powershell
# title: Get-Application
# description: Attempt to resolve the path to an Application using Get-Command or the “App Paths” registry key or the start menu search.
# version: 2.1
# type: function
# author: Joel Bennett
# license: CC0
# function: Find-Application
# x-poshcode-id: 2635
# x-archived: 2017-05-17T23:58:42
# x-published: 2011-04-26T19:28:00
#
# Returns ApplicationInfo objects if an application is found.
#
function Find-Application {
[CmdletBinding()]
param( [string]$Name )
begin {
[String[]]$Path = (Get-Content Env:Path).Split(";") |
ForEach-Object {
if($_ -match "%.*?%"){
$expansion = Get-Content ($_ -replace '.*%(.*?)%.*','Env:$1')
($_ -replace "%.*?%", $expansion).ToLower().Trim("\","/") + "\"
} else {
$_.ToLower().Trim("\","/") + "\"
}
}
}
end {
## First, try Get-Command (which searches the PATH) but suppress command not found error
$eap, $ErrorActionPreference = $ErrorActionPreference, "SilentlyContinue"
$command = Get-Command $Name -Type Application
$ErrorActionPreference = $eap
## Second, try HKLM App Paths (which are used by ShellExecute)
if(!$command) {
$AppPaths = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths"
if(Test-Path $AppPaths\$Name) {
$default = (Get-ItemProperty $AppPaths\$Name)."(default)"
if($default) {
$command = Get-Command $default.Trim("`"'") # | Select -First 1
}
}
if(!$command) {
$Name = [IO.Path]::GetFileNameWithoutExtension($Name)
if(Test-Path $AppPaths\$Name) {
$default = (Get-ItemProperty $AppPaths\$Name)."(default)"
if($default) {
$command = Get-Command $default.Trim("`"'") # | Select -First 1
}
}
}
if(!$command){
if(Test-Path "$AppPaths\$Name.exe") {
$default = (Get-ItemProperty "$AppPaths\$Name.exe")."(default)"
if($default) {
$command = Get-Command $default.Trim("`"'") # | Select -First 1
}
}
}
}
## Third, try Windows Search against the start menu as a last resort
if(!$command) {
$Name = [IO.Path]::GetFileNameWithoutExtension($Name)
$query =@"
SELECT System.ItemName, System.Link.TargetParsingPath FROM SystemIndex
WHERE System.Kind = 'link' AND System.ItemPathDisplay like '%Start Menu%' AND
( System.Link.TargetParsingPath like '%${Name}.exe' OR System.ItemName like '%${Name}%' )
"@
$Connection = New-Object System.Data.OleDb.OleDbConnection "Provider=Search.CollatorDSO;Extended Properties='Application=Windows';"
$Adapter = New-Object System.Data.OleDb.OleDbDataAdapter (New-Object System.Data.OleDb.OleDbCommand $Query, $Connection)
$DataSet = New-Object System.Data.DataSet
$Connection.Open()
if($Adapter.Fill($DataSet)) {
$command = $DataSet.Tables[0] | ForEach-Object {
Get-Command $_["System.Link.TargetParsingPath"] |
Add-Member -Type NoteProperty -Name Shortcut -Value $_["System.ItemName"] -Passthru
}
}
$Connection.Close()
}
## Now, make sure that we output everything in the right order:
## Get-Command, Keep the Shortcut value if there is one
## Then sort by the position in the PATH and make sure if it's not in there, it comes last
## Finally, sort LONG shortcut names after SHORT ones ...
## .... because we do partial matching on them, so the LONGER one matches less precisely.
$( foreach($cmd in $command) {
Get-Command $cmd.Path -ErrorAction SilentlyContinue -Type Application | ForEach-Object {
Add-Member -InputObject $_ -Type NoteProperty -Name Shortcut -Value $cmd.ShortCut -Passthru
}
}
) | Sort-Object Definition -Unique | Sort-Object {
$index = [array]::IndexOf( $Path, [IO.Path]::GetDirectoryName($_.Path).ToLower().Trim("\","/") + "\" )
if($index -lt 0) { $index = 1e5 } else { $index *= 100 }
if($_.Shortcut) {
$index += $_.Shortcut.Length
}
$index
}
}
#.Synopsis
# Finds an executable by searching the path, using Get-Command, the AppPaths registry key, and Windows Search.
#.Example
# Get-App Notepad
# Finds notepad.exe using Get-Command
#.Example
# Get-App pbrush
# Finds mspaint.exe using the "App Paths" registry key
#.Example
# &(Get-App WinWord)
# Finds, and launches, Word (if it's installed) using the "App Paths" registry key
#.Example
# Get-App "Windows PowerShell"
# Finds PowerShell.exe by searching the Start menu for the link
#.Notes
## Revision History (latest first)
## 2.1 - Fix output and sorting so that:
## - We output more than one if there is more than one,
## - But sort them by path and accuracy
## 2.0 - Add Windows Search
## 1.1 - strip quotes from results...
## 1.0 - initial release
}