I have visual studio installed, and cl.exe runs perfectly fine after vcvarsall.bat has been run in cmd but in powershell it says it is not recognized. cmd.exe
C:\Users\Ethos>vcvarsall.bat x64
**********************************************************************
** Visual Studio 2022 Developer Command Prompt v17.2.5
** Copyright (c) 2022 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'
C:\Users\Ethos>cl
Microsoft (R) C/C Optimizing Compiler Version 19.32.31332 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
usage: cl [ option... ] filename... [ /link linkoption... ]
The above works fine in cmd.
PS C:\Users\Ethos> vcvarsall.bat x64
**********************************************************************
** Visual Studio 2022 Developer Command Prompt v17.2.5
** Copyright (c) 2022 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'
PS C:\Users\Ethos> cl
cl : The term 'cl' 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
cl
~~
CategoryInfo : ObjectNotFound: (cl:String) [], CommandNotFoundException
FullyQualifiedErrorId : CommandNotFoundException
The above happens in power. Does anyone know why this happens or how to fix it?
CodePudding user response:
Note:
The following assumes that there isn't also a
vcvarsall.ps1
PowerShell script file, i.e. the PowerShell equivalent to thevcvarsall.bat
batch file.If
vcvarsall.ps1
exists, simply call it instead (.\vcvarsall.ps1
if located in the current dir, justvcvarsall.bat
if located in one of the dirs. in$env:PATH
)If it doesn't exist consider wrapping one of the solutions below in a PowerShell
function
that you can place in your$PROFILE
file; e.g.:function vcvarsall { cmd /c vcvarsall.bat @args '&&' (Get-Process -Id $PID).Path }
From PowerShell, run the following (assuming that vcvarsall.bat
is either in the current directory or in a directory listed in $env:PATH
):
cmd /c vcvarsall.bat x64 '&&' (Get-Process -Id $PID).Path
This instructs cmd.exe
to define the environment variables and then launches another PowerShell session that inherits those environment variables.
Note that the original PowerShell session will live on (as does cmd.exe
, but it exits automatically when the nested PowerShell session ends), so when you exit
the nested PowerShell session, you'll return to the original one.
Alternatively, if you prefer to start the new PowerShell session in a new window, call via cmd.exe
's start
command:
cmd /c "vcvarsall.bat x64 && start `"$([Console]::Title)`" `"$((Get-Process -Id $PID).Path)`""
As for what you tried:
For batch file vcvarsall.bat
to be effective, it must define environment variables for the current process.
This works from cmd.exe
, because batch files execute in-process there.
By contrast, PowerShell must run batch files in a cmd.exe
child process, as it cannot interpret batch files itself.
However, environment variables defined in a child process are not seen by the calling process.
Therefore, the above solutions launch an aux. cmd.exe
process first, which defines the environment variables for itself, and then launches a new PowerShell session which inherits those environment variables.