Home > Software engineering >  Can't run the command in Windows Powershell
Can't run the command in Windows Powershell

Time:12-14

I have downloaded exercism CLI and added it to the PATH. I can access it using the exercism command through cmd but on Windows Powershell, It is giving me the error that It doesn't recognize the command.

Does Powershell uses some different environment variable or am I missing something.

Here's a screenshot of the error in Powershell

The same command in cmd

Here's a screenshot of my PATH

CodePudding user response:

Something looks broken by something installed. These reg entries should be reg_expand_sz. You should not see %VARS% when viewing the path from the commandline.

get-item hkcu:\environment | % GetValueKind path
ExpandString

get-item HKLM:\SYSTEM\CurrentControlSet\Control\Session` Manager\Environment | 
  % GetValueKind path
ExpandString

CodePudding user response:

Generally speaking:

  • PowerShell respects the entries in the Path environment variable the same way that cmd does.
    • These shells only differ with respect to executing executables located in the current directory (assuming it isn't listed in Path): cmd.exe allows execution by name only (e.g., exercism), whereas PowerShell, as a security feature, requires use of a path to explicitly signal the intent (e.g., .\exercism)
    • After having modified the persistent Path definitions in the registry, a new shell session has to be started via the Windows GUI shell (Start Menu, taskbar) to see the changes. When in doubt, log off and back on again, or reboot.

Your Path value is misconfigured:

There should be no references to environment variables such as %EXERCISM% in your in-session Path value - neither cmd.exe nor PowerShell will recognize such references in this context; they interpret the entries verbatim (in contexts where variable references are recognized, only cmd.exe would recognize the syntax form %EXERCISM%; the PowerShell equivalent would be $env:EXERCISM)

In the registry, where the persistent environment-variable definitions are stored, you can base Path entries on references to other environment variables (e.g, %SystemRoot%\System32). The system itself ensures that (shell) processes see only the expanded forms of these variables. That is, what a process sees as the Path variable value is normally a ; separated list of verbatim paths (and is a concatenation of the machine-level and the user-level values).

This mechanism relies on the relevant registry Path values - in keys HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment (machine-level) and HKEY_CURRENT_USER\Environment (user-level) - to be defined as REG_EXPAND_SZ, which they are by default.

Your screenshot suggests that (at least) your user-level key has been converted to a static string value, REG_SZ, which prevents the necessary expansion of environment-variable references.

  • This quiet corruption can easily happen if you use tools such as set.exe or even the .NET [Environment]::SetEnvironmentVariable() API to update the persistent Path values - see this answer.

  • The proper way to update the persistent Path values is via direct registry access (which is unfortunate, given the complexity) - see this answer.

Fix:

Re-convert your persistent user-level Path definition to value type REG_EXPAND_SZ, as follows (works analogously for the machine-level definition, in which case elevation (run as admin) is required):

$regPath = 'registry::HKEY_CURRENT_USER\Environment'
Set-ItemProperty -Type ExpandString -LiteralPath $regPath Path (Get-ItemPropertyValue -LiteralPath $regPath Path)
  • Related