How can I use PowerShell with the Visual Studio Command Prompt?
Solution 1
Stealing liberally from blog post Replace Visual Studio Command Prompt with PowerShell, I was able to get this to work. I added the following to my profile.ps1 file and all is well with the world.
pushd 'c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC'
cmd /c "vcvarsall.bat&set" |
foreach {
if ($_ -match "=") {
$v = $_.split("="); set-item -force -path "ENV:\$($v[0])" -value "$($v[1])"
}
}
popd
write-host "`nVisual Studio 2010 Command Prompt variables set." -ForegroundColor Yellow
This has worked well for years - until Visual Studio 2015. vcvarsall.bat no longer exists. Instead, you can use the vsvars32.bat file, which is located in the Common7\Tools folder.
pushd 'C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools'
cmd /c "vsvars32.bat&set" |
foreach {
if ($_ -match "=") {
$v = $_.split("="); set-item -force -path "ENV:\$($v[0])" -value "$($v[1])"
}
}
popd
write-host "`nVisual Studio 2015 Command Prompt variables set." -ForegroundColor Yellow
Things have changed yet again for Visual Studio 2017. vsvars32.bat
appears to have been dropped in favor of VsDevCmd.bat
. The exact path may vary depending on which edition of Visual Studio 2017 you're using.
pushd "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\Tools"
cmd /c "VsDevCmd.bat&set" |
foreach {
if ($_ -match "=") {
$v = $_.split("="); set-item -force -path "ENV:\$($v[0])" -value "$($v[1])"
}
}
popd
Write-Host "`nVisual Studio 2017 Command Prompt variables set." -ForegroundColor Yellow
You can also make the split create just two items to avoid breaking values including the equal sign, which is also the separator of the environment variable name and the value:
$v = $_.split("=", 2); set-item -force -path "ENV:\$($v[0])" -value
Minor Changes for Visual Studio 2022, now that it's 64-bit.
pushd "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools"
cmd /c "VsDevCmd.bat&set" |
foreach {
if ($_ -match "=") {
$v = $_.split("=", 2); set-item -force -path "ENV:\$($v[0])" -value "$($v[1])"
}
}
popd
Write-Host "`nVisual Studio 2022 Command Prompt variables set." -ForegroundColor Yellow
Solution 2
The simplest option is to run the VS 2010 command prompt and then start PowerShell.exe. If you really want to do this from your "home" PowerShell prompt, the approach you show is the way to go. I use a script that Lee Holmes wrote a while back:
<#
.SYNOPSIS
Invokes the specified batch file and retains any environment variable changes
it makes.
.DESCRIPTION
Invoke the specified batch file (and parameters), but also propagate any
environment variable changes back to the PowerShell environment that
called it.
.PARAMETER Path
Path to a .bat or .cmd file.
.PARAMETER Parameters
Parameters to pass to the batch file.
.EXAMPLE
C:\PS> Invoke-BatchFile "$env:VS90COMNTOOLS\..\..\vc\vcvarsall.bat"
Invokes the vcvarsall.bat file to set up a 32-bit dev environment. All
environment variable changes it makes will be propagated to the current
PowerShell session.
.EXAMPLE
C:\PS> Invoke-BatchFile "$env:VS90COMNTOOLS\..\..\vc\vcvarsall.bat" amd64
Invokes the vcvarsall.bat file to set up a 64-bit dev environment. All
environment variable changes it makes will be propagated to the current
PowerShell session.
.NOTES
Author: Lee Holmes
#>
function Invoke-BatchFile
{
param([string]$Path, [string]$Parameters)
$tempFile = [IO.Path]::GetTempFileName()
## Store the output of cmd.exe. We also ask cmd.exe to output
## the environment table after the batch file completes
cmd.exe /c " `"$Path`" $Parameters && set > `"$tempFile`" "
## Go through the environment variables in the temp file.
## For each of them, set the variable in our local environment.
Get-Content $tempFile | Foreach-Object {
if ($_ -match "^(.*?)=(.*)$")
{
Set-Content "env:\$($matches[1])" $matches[2]
}
}
Remove-Item $tempFile
}
Note: this function will be available in the PowerShell Community Extensions 2.0 module-based release coming soon.
Solution 3
I found a simple method here: modify the shortcut.
The original shortcut is something like this:
%comspec% /k ""C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\VsDevCmd.bat""
Add & powershell
before the last quote, like this:
%comspec% /k ""C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\VsDevCmd.bat" & powershell"
If you want to make it look more like PowerShell, go to the Colors tab of the shortcut properties and set the Red, Green and Blue values to 1, 36 and 86 respectively.
Solution 4
To (a) provide Visual Studio 2013 support; (b) combine the best of two previous answers; and (c) provide a function wrapper:
This builds on Andy's technique (which builds on Allen Mack's technique as Andy indicated (which in turn builds on Robert Anderson's technique as Allen indicated (all of which had a slight glitch as indicated on this page by the user known only as "me--", so I took that into account as well))).
Here is my final code--note the use of the non-greedy quantifier in the regex to handle any possible embedded equals in the values. That also happens to simplify the code: a single match instead of a match then split as in Andy's example or a match then indexof and substrings as in "me--"'s example).
function Set-VsCmd
{
param(
[parameter(Mandatory, HelpMessage="Enter VS version as 2010, 2012, or 2013")]
[ValidateSet(2010,2012,2013)]
[int]$version
)
$VS_VERSION = @{ 2010 = "10.0"; 2012 = "11.0"; 2013 = "12.0" }
$targetDir = "c:\Program Files (x86)\Microsoft Visual Studio $($VS_VERSION[$version])\VC"
if (!(Test-Path (Join-Path $targetDir "vcvarsall.bat"))) {
"Error: Visual Studio $version not installed"
return
}
Push-Location $targetDir
cmd /c "vcvarsall.bat&set" |
foreach {
if ($_ -match "(.*?)=(.*)") {
Set-Item -force -path "ENV:\$($matches[1])" -value "$($matches[2])"
}
}
Pop-Location
Write-Host "`nVisual Studio $version Command Prompt variables set." -ForegroundColor Yellow
}
Solution 5
Keith has already mentioned PowerShell Community Extensions (PSCX), with its Invoke-BatchFile
command:
Invoke-BatchFile "${env:ProgramFiles(x86)}\Microsoft Visual Studio 12.0\VC\vcvarsall.bat"
I also noticed that PSCX also has an Import-VisualStudioVars
function:
Import-VisualStudioVars -VisualStudioVersion 2013
Andy S
Software engineer, gamer, home remodeler, movie buff and erstwhile rock climber. Little known fourth member of Rod Torkelson's Armada Featuring Herman Menderchuk.
Updated on April 26, 2022Comments
-
Andy S about 2 years
I've been using Beta 2 for a while now and it's been driving me nuts that I have to punt to cmd.exe when running the Visual Studio 2010 Command Prompt. I used to have a nice vsvars2008.ps1 script for Visual Studio 2008. Is there a vsvars2010.ps1 script or something similar?
-
czuroski almost 12 yearsI agree - this also worked perfectly for me. I also had to change the path to visual studio in Program Files (not x86), since I am not on a 64 bit system.
-
Andy S almost 12 yearsJust a quick note that this same technique works for Visual Studio 2012. Simply change "Microsoft Visual Studio 10.0" to "Microsoft Visual Studio 11.0"
-
Matt Stephenson about 11 years
echo $Profile
to see the intended path for your profile.ps1, if you've never created it -
sakra almost 10 yearsFor PowerShell 2.0 compatibility the param section requires
[parameter(Mandatory=$true,
... -
Mark Meuer almost 9 yearsStraightforward and works like a charm. This answer deserves more upvotes.
-
orad almost 9 yearsThe only thing I don't like about this, is that it keeps a redundant cmd.exe process loaded. Other than that is a nice solution.
-
orad almost 9 yearsAs of PSCX 3.2.0, VS 2015 is not supported in this cmdlet. I opened an issue for it.
-
Oleg Sych over 8 yearsFirst off, thanks to all contributors to this answer; I've been coming back to this page for years. To save the hassle of changing my profile manually, I've created posh-vs, a module that I can install from the PowerShell Gallery and modify my profile with two commands:
Install-Module posh-vs
andInstall-PoshVs
. I hope others will find it useful. -
stijn over 8 yearsNice, but would imo be nicer without the pushd/popd. Just use something like
cmd /c """$targetDir\vcvarsall.bat""&set"
-
Chris Simmons over 8 yearsThe script itself works wonderfully. A note of caution, though (possibly): As the Package Manager Console in Visual Studio is itself a PowerShell host, this script will get run there as well. This doesn't appear to be a problem until you notice that "Run without debugging" or any other functions or plugins run that launch a standard Windows console will not work after the PMC is initialized. I worked around this by, instead of saving the script in this answer to "profile.ps1", I saved it to "Microsoft.PowerShell_profile.ps1" so that it only gets run in a "proper" PowerShell session.
-
Voo over 8 yearsIt's really bad practice to hardcode the paths when there are perfectly fine environment variables (VS140COMNTOOLS for VS2015) to use. That will even work for custom VS installs.
-
Lekensteyn about 8 yearsWorks for MSVC12 too, though I had to set
vcvarsall.bat x64
to avoid strange linking errors ("unresolved external symbol"). Likely becausevcvarsall.bat
loads a 32-bit environment. -
Andy S over 7 yearsI appreciate the desire to use environment variables, but those variables appear to be initialized by the very batch file we're trying to extract variables from. I would be happy to see evidence to the contrary. I have a clean Windows 10 install with a clean Visual Studio 2017 install and no VS150COMNTOOLS environment variable until I execute VsDevCmd.bat.
-
error about 7 yearsPassing
2
as the second parameter toSplit
will allow=
in environment variable values. -
Squirrelkiller almost 6 yearsHey nice addition. Update it with the VS2015/17 versions too? This is the first google result, I think your addition will help people.
-
Chronial almost 4 yearsYou can find info on how to find the visual studio installation here: devblogs.microsoft.com/cppblog/…
-
Emmanuel Oga almost 4 years10 years later this is still a problem :-(
-
stijn about 3 yearsA word of warning since this is like the canonical answer on how to do this: the caveat is it it copies over all environment variables which can have unexpected results. Alternative would be to e.g. first call
cmd /c set
and then after doing the same with the batchfile figure out which variables were added/changed and only copy those, since the chances are high only those are the ones effectively set by vcvarsall.bat. -
Peter Mortensen over 2 yearsWhy? What is the reason? What advantages does it have? Please respond by editing (changing) your answer, not here in comments (without "Edit:", "Update:", or similar - the answer should appear as if it was written today).
-
Peter Mortensen over 2 yearsWhy does a C++ compiler enter the picture?
-
MatrixManAtYrService over 2 yearsSorry @PeterMortensen, I can't remember why the above hijinks were necessary, or why I preferred them to the alternatives. The only thought I can summon when I look at this is that I should've switched to vim sooner.
-
olin000 over 2 years@PeterMortensen AFAIR it was more to demonstrate how PowerShell can be not only started from Visual Studio Code Command Prompt, but also how it can be used in a more complex case, like the one with running C++ compiler with attributes.
-
vlabatut almost 2 yearsWith VS 2019 it is no longer an issue, there a new Launch-VsDevShell.ps1 script that is shipped with Visual Studio.
-
peidaqi almost 2 yearsExcellent script. Only minor thing is that it sets up x86 instead of x64 environment in VS2022. Solution is to replace the folder with "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build" and cmd with "vcvars64.bat&set". You can run cl.exe to confirm.