1

I have a Powershell script on Win10 that needs to start multiple other programs, and finding that in a lot of cases I have to go looking for the full path to the executable file, and potentially hard-code that path in the script, which is not great for robustness or portability between machines.

On *nix systems, it is expected that most programs can be started from the command line, so each application will generally either add its install folder to the PATH environment variable, or be inserted (e.g. via symlinks) into a directory like /usr/bin that's already in the PATH.

Microsoft discourages the use of the PATH variable. Instead applications are SUPPOSED to insert a key for their main .exe file into one of two places in the registry, depending on whether the app is installed for one user or all users-

  • HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\App Paths
  • HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\App Paths

The (default) value under that key is the full path to the executable file.

(ref. https://learn.microsoft.com/en-us/windows/win32/shell/app-registration#finding-an-application-executable)

Except- it seems an awful lot of applications don't follow this recommendation. (Micrsoft's own PowerToys, Keepass2, FreeFileSync, Free Download Manager are just some examples).

These programs do (when not installed as portable apps) have a presence in the Registry, it's just not in the officially recommended places.

So, my question is- Is there an effective way to get a good (not necessarily perfect) general answer to the question "what is the full path to installed program X.exe" on Windows? at least where that program has saved a path somewhere in the registry.

This is similar to the question asked here- Equivalent of *Nix 'which' command in PowerShell? but with the important difference that I want to include "badly behaved" programs that don't correctly configure the PATH or the two registry keys described above.

Ideally this would be a function that could be called on the fly with the program name as a parameter that returns the pathname, but worst case if it requires a brute force search across the whole registry to find and then de-duplicate all the paths to .exe files under the %PROGRAMFILES% folders (64 and 32 bit), I guess I could run this once and save the result in a file as a hash table.

Incans
  • 182
  • 9
  • I think your conditions are so specific, that the only way to solve your problem, is a file system search for `.exe`. Just in case an installed software has neither registry entries nor path entries. – stackprotector Sep 04 '22 at 08:07
  • Yes, interesting point. I'd been thinking about trying to query the Start menu configuration, but the start menu generally contains shortcuts, so you would then have to iterate across all the shortcuts to see where they point. The filesystem object in Powershell does look to have decent capabilities for recursively searching and filtering directories. It would be too slow to do on the fly, but in principle it might be possible to search all the main program folders for .exe files, and then insert the paths into the App Paths registry key. Basically fixing the apps gap in installation. – Incans Sep 04 '22 at 14:36
  • To narrow down the question, you should define the state for a software to be considered installed and the state when it is not. I recommend to not use the pure existence of binaries to consider a software installed. PuTTY, for example, is a small executable and it is enough to just copy that binary to a system in order to use it. But to consider it installed, it should be "easy to access", like being available in the PATH, imo. – stackprotector Sep 04 '22 at 16:12
  • In other words, you are trying to fix the symptoms of a problem and not the reason. The reason is, that some software has not been installed properly ;) – stackprotector Sep 04 '22 at 16:14
  • >> In other words, you are trying to fix the symptoms of a problem and not the reason. Well maybe, but these packages have all been installed using the developers own recommended MSI installer, so as far as the vendor/maintainer is concerned they are "installed", they just aren't following the Microsoft guidelines for installation when it comes to shell paths. I have logged bugs/RFEs with several of the maintainers, but I can't guarantee they will update their installer to suit me, so in the meantime I need a workable solution. – Incans Sep 04 '22 at 16:34

1 Answers1

0

For MSI packages you could do:

$software = Get-CimInstance -Query "select Vendor,Name,Version,InstallLocation,Language from win32_product" | Select-Object -Property Vendor,Name,Version,InstallLocation,Language

Output:

enter image description here

This gives you at least the install location.

You may also take a look at get-StartApps, e.g.:

Get-StartApps  | ?{$_.appid -match "\.exe"}

enter image description here

Toni
  • 1,738
  • 1
  • 3
  • 11
  • Another good idea thanks. I know very little about the Windows MSI installer, so I wouldn't have known where to start on this approach. – Incans Sep 04 '22 at 14:37
  • Welcome to [SO]! You already used code formatting to beautifully display code. Please also use it to display console output. Screenshots of plain text are disadvantageous for many reasons (different font sizes, no C&P, bandwidth,...) – stackprotector Sep 04 '22 at 16:19