Sedat Kapanoglu
Sedat Kapanoglu

Reputation: 47680

How to get path to the correct PowerShell executable?

This question has been asked before, but PowerShell has since gone through several phases that it even has a different executable name now (pwsh.exe). All answers assume powershell.exe will never change.

Is there a cross-platform way on .NET to get path to the latest (or preferably, user-preferred) PowerShell executable without resorting to "try to find pwsh.exe in the PATH first, if it doesn't work, try finding powershell.exe" trickery? Obviously, that approach can fail someday too if pwsh.exe changes its name again. Not to mention that a user's preferences might be different than what's installed on the system.

Even MS-DOS had this feature with COMSPEC environment variable, let alone Unix and its SHELL variable. I'm surprised that PowerShell doesn't have this.

Perhaps, it's possible to get that information from PowerShell's runtime variables, but I'll be calling it from an external .NET process.

Upvotes: 3

Views: 8506

Answers (1)

mklement0
mklement0

Reputation: 439777

  • There is no correct PowerShell executable:

    • Window PowerShell is the legacy, ships-with-Windows, Windows-only PowerShell edition whose latest and last version is 5.1 and which will receive critical security fixes only.

      • The location of its executable, powershell.exe, is the same for all its versions[1] (expressed in C# terms):

        System.Environment.ExpandEnvironmentVariables(
          @"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe"
        );
        
      • Note: If your application is a 32-bit application and you want to target the 64-bit PowerShell executable, replace System32 with SysNative; conversely, in order to target the 32-bit PowerShell executable from a 64-bit application, replace System32 with SysWOW64

    • PowerShell (Core) 7+ is its modern, cross-platform, install-on-demand successor, which is actively maintained.

      • This edition's executable name differs from that of Window PowerShell: it is pwsh.exe (on Windows) / pwsh (on Unix-like platforms).

        • As this edition evolves, it is highly unlikely that its executable name will change, given the continued commitment to backward compatibility (within reason).
      • Unlike Windows PowerShell, PowerShell (Core) allows multiple versions to be installed side-by-side, in potentially arbitrary locations.

    • The system-defined ComSpec environment variable contains the full path to what is still the default shell on Windows, cmd.exe (the legacy Command Prompt), and that is unlikely to change for reasons of backward compatibility.

      • No analogous environment variable was ever defined for PowerShell, given that it isn't the default shell.

      • As an aside: Unix-like platforms rely on "convention over configuration" and assume that the default shell is in a fixed location, namely /bin/sh


Given the above, your best bet on Windows[2] is indeed to:

  • Look for pwsh.exe via the Path environment variable: that is, consider the pwsh.exe executable, if any, found in the first directory listed in the Path environment variable to be the current user's preferred version.

    • See the answers to this post for how to locate an executable via Path in C#.

    • As Tu deschizi eu inchid points out, a potential alternative is to consult the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShellCore\InstalledVersions registry key for installed PowerShell (Core) versions (this answer shows VB.NET code that examines this key); however, note that:

      • This key is only created if PowerShell (Core) is installed via the MSI installer (which includes installation via the Microsoft Store and winget.exe), which, however, is just one way to install it (see an overview of all available installation methods here), so this may cause you to miss installations.

      • Conversely, a version installed this way isn't necessarily discoverable via the Path environment variable, and if it isn't, may signal the intent that it is a "private" installation.

  • And, if not found, fall back to powershell.exe's full path, which can be determined as shown above.

As a general caveat, given that you're willing to target whatever PowerShell version is available:

  • If you're willing to target Windows PowerShell as a fallback, any PowerShell code you use will have to be cross-edition compatible.
  • Even in the realm of PowerShell (Core) alone you'll need to be aware of features that are only available in later versions.

[1] Note that only ever one version of Windows PowerShell can be installed at a time, which in recent Windows version is the last one, v5.1. However, since v3, also running v2 (only) has been possible via a command-line parameter of the one and only powershell.exe executable (-version 2), assuming that v2 of .NET Framework is installed (which is no longer true by default in recent Windows versions).

[2] on Unix-like platforms, by definition there can only ever be (potentially multiple versions of) PowerShell (Core).

Upvotes: 7

Related Questions