From PowerShell, how can the location of an executable be resolved?
Asked Answered
H

3

7

On many occasions I have needed a path to an executable or command line tool, for example: notepad or kubectl. Whilst using PowerShell, the executable is available, but the physical location of the file has not always been easy to find.

One way is to search every folder on the PATH, or even worse the system ( gci -r | % { $_ ...}), but this is not the most efficient use of time, to re-code every time. Is there a better way?

Hoke answered 25/6, 2021 at 13:49 Comment(1)
superuser.com/questions/675837/…Couldst
S
13

Get-Command will return an object that contains several fields with the pathname. For example, if I type Get-Command notepad on my system, I get

PS Z:\> Get-Command notepad

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Application     notepad.exe                                        10.0.18... C:\WINDOWS\system32\notepad.exe

and if I type Get-Command notepad | Select-Object * I will get

PS Z:\> Get-Command notepad | Select-Object *                               
                                                                            
                                                                            
HelpUri            :                                                        
FileVersionInfo    : File:             C:\WINDOWS\system32\notepad.exe      
                     InternalName:     Notepad                              
                     OriginalFilename: NOTEPAD.EXE.MUI                      
                     FileVersion:      10.0.18362.1 (WinBuild.160101.0800)  
                     FileDescription:  Notepad                              
                     Product:          Microsoft® Windows® Operating System 
                     ProductVersion:   10.0.18362.1                         
                     Debug:            False                                
                     Patched:          False                                
                     PreRelease:       False                                
                     PrivateBuild:     False                                
                     SpecialBuild:     False                                
                     Language:         English (United States)              
                                                                            
Path               : C:\WINDOWS\system32\notepad.exe                        
Extension          : .exe                                                   
Definition         : C:\WINDOWS\system32\notepad.exe                        
Source             : C:\WINDOWS\system32\notepad.exe                        
Version            : 10.0.18362.1316                                        
Visibility         : Public                                                 
OutputType         : {System.String}                                        
Name               : notepad.exe                                            
CommandType        : Application                                            
ModuleName         :                                                        
Module             :                                                        
RemotingCapability : PowerShell                                             
Parameters         :                                                        
ParameterSets      :                                                        
                                                                            
Such answered 25/6, 2021 at 14:3 Comment(0)
H
4

I recently discovered Where.exe is available to PowerShell.

> Where.exe kubectl
C:\Program Files\Docker\Docker\resources\bin\kubectl.exe

This is compatible with PowerShell variables so can be used whilst scripting: $path = where.exe notepad

Hoke answered 25/6, 2021 at 13:49 Comment(0)
N
0

The 'Get-Command' or "where.exe' are too restrictive, they can't be use for all programms ... Bellow 2 functions that work fine, one to get ShortCut informations, one to get Application information that I use in all my scripts :

Function Get-ShortCut {
param (
    [string]$StringToSearch,
    [array]$Directories = @(
        "${Env:PROGRAMDATA}\Microsoft\Windows\Start Menu\Programs"
        "${Env:APPDATA}\Microsoft\Windows\Start Menu\Programs"
    ),
    [string]$TypeTargetFile = "exe"
)
$ShortCutArray = @()
$shellObject = New-Object -ComObject WScript.Shell
foreach ($Directory in $Directories) {
    $shortcuts = Get-ChildItem -Path $Directory -Recurse -Filter *.lnk
    foreach ($shortcut in $shortcuts) {
        $ShortcutObject = $shellObject.CreateShortcut($shortcut.FullName)
        if (($ShortcutObject.TargetPath -like "*$StringToSearch*.$TypeTargetFile") -or ($shortcut.BaseName -like "*$StringToSearch*")) {
            $ShortCutArray += [PSCustomObject]@{
                Name = $shortcut.BaseName
                Path = $shortcut.FullName
                TargetPath = $ShortcutObject.TargetPath
                Arguments = $ShortcutObject.Arguments
                WorkingDirectory = $ShortcutObject.WorkingDirectory
                IconLocation = $ShortcutObject.IconLocation
                Description = $ShortcutObject.Description
                WindowStyle = $ShortcutObject.WindowStyle
                Hotkey = $ShortcutObject.Hotkey
            }
        }
    }
}
Return $ShortCutArray

} }

Function Get-Application {
param (
    [string]$StringToSearch
)
$hives = @(
    "HKLM"
    "HKCU"
)
$RegistryKeys = @(
    "\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
    "\SOFTWARE\Wow6432node\Microsoft\Windows\CurrentVersion\Uninstall"
)
$ApplicationArray = @()
ForEach ($hive in $hives) {
    ForEach ($RegistryKey in $RegistryKeys) {
        if (Test-Path "${hive}:${RegistryKey}" -ErrorAction SilentlyContinue) {
            $Applications = Get-ChildItem "${hive}:${RegistryKey}" | ForEach-Object { Get-ItemProperty $_.PsPath } | Select DisplayName,DisplayVersion,InstallDate,UninstallString | Where-Object {$_.DisplayName -match "$StringToSearch"}
            ForEach ($Application in $Applications) {
                $DisplayName = $Application.DisplayName
                $DisplayVersion = $Application.DisplayVersion
                $UninstallString = $Application.UninstallString -Replace "`"",""
                $InstallDate = $Application.InstallDate

                $ApplicationShortCuts = Get-ShortCut $StringToSearch
                if ($ApplicationShortCuts.Count -gt 1) {
                    $WorkingDirectory = $ApplicationShortCuts.WorkingDirectory[0]
                    $TargetPath = $ApplicationShortCuts.TargetPath[0]
                    $Arguments = $ApplicationShortCuts.Arguments[0]
                } else {
                    $WorkingDirectory = $ApplicationShortCuts.WorkingDirectory
                    $TargetPath = $ApplicationShortCuts.TargetPath
                    $Arguments = $ApplicationShortCuts.Arguments
                }
                if ((-not $WorkingDirectory) -and $TargetPath) {$WorkingDirectory = Split-Path -Path $TargetPath -Parent}
                $ApplicationArray += [PSCustomObject]@{
                    Name = $DisplayName
                    Version = $DisplayVersion
                    InstallDate = $InstallDate
                    Directory = $WorkingDirectory
                    Command = $TargetPath
                    Arguments = $Arguments
                    UninstallCommand = $UninstallString
                }
            }
        }
    }
}
if (-not $ApplicationArray) {
    $ApplicationShortCuts = Get-ShortCut $StringToSearch
    forEach($ApplicationShortCut in $ApplicationShortCuts) {
        $ApplicationName = $ApplicationShortCut.Name
        $WorkingDirectory = $ApplicationShortCut.WorkingDirectory
        $TargetPath = $ApplicationShortCut.TargetPath
        $Arguments = $ApplicationShortCut.Arguments
        if ((-not $WorkingDirectory) -and $TargetPath) {$WorkingDirectory = Split-Path -Path $TargetPath -Parent}

        $ApplicationArray += [PSCustomObject]@{
            Name = $ApplicationName
            Version = $Null
            InstallDate = $Null
            Directory = $WorkingDirectory
            Command = $TargetPath
            Arguments = $Arguments
            UninstallCommand = $Null
        }
    }
}
Return $ApplicationArray

}

Example :

Get-Application Edge
Name             : MSEdgeRedirect

Version : 0.7.4.0 InstallDate : 20230830 Directory : C:\Program Files (x86)\Microsoft\Edge\Application Command : C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe Arguments : UninstallCommand : C:\Program Files\MSEdgeRedirect\MSEdgeRedirect.exe /uninstall

Name : Microsoft Edge Version : InstallDate : 20230612 Directory : C:\Program Files (x86)\Microsoft\Edge\Application Command : C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe Arguments : UninstallCommand : C:\Program Files (x86)\Microsoft\Edge\Application\Installer\setup.exe --uninstall --msedge --channel=stable --system-level --verbose-logging

Name : Microsoft Edge Update Version : 1.3.175.29 InstallDate : Directory : C:\Program Files (x86)\Microsoft\Edge\Application Command : C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe Arguments : UninstallCommand :

Nolpros answered 5/12, 2023 at 16:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.