I installed AWS SAM from the msi installer from AWS for windows.
after running the installer, I ran sam --version
in cmd and powershell.
PS C:\Users\dgupta> sam --version
SAM CLI, version 1.26.0
It returns the version I just installed. However in VS code, I opened a terminal and ran sam --version
it errors out.
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
Try the new cross-platform PowerShell https://aka.ms/pscore6
sam : The term 'sam' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, g of the name,
or if a path was included, verify that the path is correct and try again.
At line:1 char:1
+ sam --version
+ ~~~
+ CategoryInfo : ObjectNotFound: (sam:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
why is this happening ? doesn't VS Code terminal and normal terminal have access to the same environment variables ?
It's impossible to diagnose your problem without further information, but perhaps these troubleshooting tips help:
If invoking an external executable (sam
) by name only fails, the problem must be that the directory in which the executable resides isn't listed in the $env:PATH
environment variable defined for the current process.
However, it is possible that the external sam
executable's directory isn't in $env:PATH
and that sam
is an auxiliary PowerShell command of the same name that knows the true sam
's location and invokes it behind the scenes.
For instance an alias - such as New-Alias sam 'C:\path\to\sam.exe'
- or a function - such as function sam { & C:\path\to\sam.exe $args }
- may be defined.
From the PowerShell session where sam
is found:
sam
refers to in your session, use the following and check the value of the CommandType
column:Get-Command sam
If the command type is Application
, you are indeed dealing with an external executable, and the Source
column will report its full path, from which you can glean the executable's directory path (which you can determine directly with Split-Path (Get-Command -Type Application sam).Path
$env:PATH
in the other session - see first section below.If the command type isn't Application
:
$PROFILE
variable) were loaded.Diagnose why a directory is missing from $env:PATH
on Windows:[1]
Possible reasons:
You've just installed an executable, and the installer modified the persistent $env:PATH
definition in the registry.
Any running processes started before this modification or even ones started afterwards directly from such processes, i.e. as child processes, do not see the modification.
Solution:
Start a new session, which in your case means restarting Visual Studio Code, but be sure to start it from the Start Menu / taskbar / File Explorer, as they are aware of the modified environment. When in doubt, log off and back on to your Windows session, or reboot your machine.
Alternatively, refresh $env:PATH
from the registry in-session - see below.
Something in your current PowerShell session has (possibly inadvertently) removed sam
's directory from the in-process $env:PATH
variable.
Solution:
$env:PATH
definition from the registry with the following command (note that any prior in-process modifications are then lost):$env:PATH =
[Environment]::GetEnvironmentVariable('Path', 'Machine') + ';' +
[Environment]::GetEnvironmentVariable('Path', 'User')
If these solutions don't help (persistently), the problem must be :
Either: Even the persistent Path
variable definition is lacking an entry for the directory or interest (even though installers normally do add such an entry).
Or: The problem arises from what PowerShell profile files are loaded into the different environments.
For instance, if a given profile file adds a relevant $env:PATH
entry dynamically to every session, a different environment, such as Visual Studio Code, may not load the same profile file.
See the next sections.
Add a directory entry to the persistent definition of the Path
environment variable yourself, on Windows:[1]
If you don't know which directory to add to the Path
variable, you can locate it via a command such as the following:
# Find the directory/ies on drive C: that contain a "sam.exe" file.
Get-ChildItem C:\ -Filter sam.exe -Recurse -File -ErrorAction Ignore |
ForEach-Object DirectoryName
Interactively:
Run sysdm.cpl
, select the Advanced
tab, and click on Environment Variables...
, then modify the Path
variable as desired.:
Note: To modify the Path
variable under System variables
, i.e. the system-wide part of the Path
variable, you need to be an administrator.
After having modified Path
this way, you need to open a new shell session in the manner described above in order to see the effects.
Programmatically:
Add-Path
; the answer also explains why set.exe
should not be used.Diagnose what profile files were loaded into a session, on all platforms:
PowerShell's profile files are (by default) loaded (dot-sourced) on session startup and allow sessions to be customized, which can include things such as custom alias definitions, functions, and even in-process $env:PATH
additions.
There are multiple profile files, all of which are loaded (by default), if present, along two independent dimensions: all-users vs. current-user, and all-hosts vs. current-host (a host being the PowerShell host environment, such as a regular console window or the terminal in Visual Studio Code).
The automatic $PROFILE
variable reports the current-user, current-host profile-file path, but actually has normally invisible properties listing all paths (you can make them visible with $PROFILE | select *
- see this answer).
What profiles are loaded into a session for a given user is determined by the following factors:
Fundamentally, whether profile loading is suppressed altogether, using the CLI's -NoProfile
switch.
If not suppressed (the default, even with -Command
and -File
invocations):
What edition of PowerShell you're using: The comes-with Windows, legacy, Windows-only Windows PowerShell edition (whose latest and final version is 5.1), whose CLI is powershell.exe
, vs. the install-on-demand, cross-platform PowerShell (Core) edition, whose CLI is pwsh
, have separate profile locations.
The type of the host environment, as reflected in the automatic $Host
variable.
To see what command line was used to invoke the current session, run the following:
[Environment]::CommandLine
Note:
-NoProfile
among the parameters, but profiles may still be loaded during startup - see below.It follows from the above that different host environments load different sets of profile files, and in the PIC (PowerShell Integrated Console) that comes with the PowerShell extension and which runs in Visual Studio Code's integrated terminal, different profile files are indeed loaded, IF enabled via the PowerShell: Enable Profile Loading
setting - compared to regular console windows[2]
If you want your PIC sessions to load the same current-user profile as regular console windows:
Via Visual Studio Code's settings, first make sure that the PowerShell: Enable Profile Loading
setting is enabled and start a new PIC session, if necessary.
From a PIC session, run psedit $PROFILE
to open the host-specific current-user profile for editing.
Add the following content:
. ($PROFILE -replace '\.VSCode', '.PowerShell')
[1] Note that Unix-like platforms have no standardized mechanism for defining persistent environment variables, which is why neither PowerShell nor .NET provide APIs for it.
[2] Note that you can use PowerShell in the Visual Studio Code terminal even without the PowerShell extension, as a general-purpose shell, and such session do use the same profiles as regular console windows - see this answer.