I cannot run winget
although it is in the path :
PS C:\> $env:path -split ';' | sls WindowsApps
%USERPROFILE%\AppData\Local\Microsoft\WindowsApps
PS C:\>
and winget
is present in the %USERPROFILE%\AppData\Local\Microsoft\WindowsApps\
directory :
PS C:\> ls $env:USERPROFILE\AppData\Local\Microsoft\WindowsApps\winget.exe
Directory: C:\Users\sebastien.mansfeld\AppData\Local\Microsoft\WindowsApps
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---l 15/11/2023 18:13 0 winget.exe
PS C:\> winget.exe
winget.exe : The term 'winget.exe' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path
was included, verify that the path is correct and try again.
At line:1 char:1
+ winget.exe
+ ~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (winget.exe:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
PS C:\>
I was expecting winget
to run because it's in the PATH.
Why is this not working ?
tl;dr
Fix your user-level Path
environment-variable definition in the registry as follows:
& {
param($key)
Set-ItemProperty -Type ExpandString $key Path (Get-ItemPropertyValue $key Path)
} registry::HKEY_CURRENT_USER\Environment
In order for future PowerShell sessions to see this change, either log off and back on, or - if acceptable - kill all explorer.exe
instances to force a restart of the Windows (GUI) shell, using Stop-Process -Name explorer.exe
You may also want to call the above with registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
to fix the machine-level definitions, however:
Only do so if you find the registry value to be of type REG_SZ
(instead of the expected REG_EXPAND_SZ
)
Given your symptom, this condition is implied for your user-level definition (see next section).
Generally, it takes extra effort to retrieve the unexpanded data stored in a REG_EXPAND_SZ
-typed registry value - see this answer.
Doing so requires running with elevation (as administrator).
If the process-level instance of the Path
environment variable - as reflected in $env:Path
- contains unexpanded cmd.exe
-style environment-variable references such as %USERPROFILE%
, the implication is that the registry-based definition(s) of the variable was corrupted.
That is, the original REG_EXPAND_SZ
-typed definition of the Path
environment variable in the registry was accidentally changed to REG_SZ
, which can easily happen if you use utilities such as setx.exe
or the System.Environment.SetEnvironmentVariable
.NET API to update these definitions.
$env:PATH
- which is lamentably cumbersome - see this answer.The process-level value of the Path
environment variable is the concatenation of the expanded value of the composite value of the Path
values of the following registry keys, in order:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
(machine-level)HKEY_CURRENT_USER\Environment
(user-level)If the registry values were accidentally changed to REG_SZ
(literal strings), no expansion of cmd.exe
-style environment-variable references such as %USERPROFILE%
takes place.
Since attempts to invoke executables by name only (e.g. winget.exe
) use the directories listed in the value of Path
verbatim, a directory literally named %USERPROFILE%\AppData\Local\Microsoft\WindowsApps
, for instance, won't be found.
Changing the type of the registry value back to REG_EXPAND_SZ
(ExpandString
in .NET terms), as shown in the top section, ensures that cmd.exe
-style environment-variable references are again automatically expanded before they're stored in the process-level Path
value.