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?
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
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.
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.
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
}
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
Kudos to Andy S for his answer. I've been using his solution for a while, but I ran into a problem today. Any value that has an equals sign in it is truncated at the equals sign. For example, I had:
JAVA_TOOL_OPTIONS=-Duser.home=C:\Users\Me
But my PowerShell session reported:
PS C:\> $env:JAVA_TOOL_OPTIONS
-Duser.home
I fixed this by modifying my profile script to the following:
pushd 'c:\Program Files (x86)\Microsoft Visual Studio 11.0\VC'
cmd /c "vcvarsall.bat&set" |
foreach {
if ($_ -match "=") {
$i = $_.indexof("=")
$k = $_.substring(0, $i)
$v = $_.substring($i + 1)
Set-Item -force -path "ENV:\$k" -value "$v"
}
}
popd
Using 'Modules' and VsDevShell is much simpler and cleaner. A simple Powershell script is the following which works for MSVC and Clang:
param(
[String] $Compiler = "MSVC"
)
if ($Compiler -ne "MSVC" -and $Compiler -ne "Clang") {
Write-Error "Unknown compiler '$Compiler'; must be MSVC or Clang"
Exit -1
}
Write-Host "======================================="
Write-Host "Setting up environment variables..."
# Visual Studio path <https://github.com/microsoft/vswhere/wiki/Find-VC>
$vsPath = &"${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationpath
Write-Host "Microsoft Visual Studio path = '$vsPath'"
# Use module `Microsoft.VisualStudio.DevShell.dll`
Import-Module (Get-ChildItem $vsPath -Recurse -File -Filter Microsoft.VisualStudio.DevShell.dll).FullName
Enter-VsDevShell -VsInstallPath $vsPath -SkipAutomaticLocation -DevCmdArguments '-arch=x64'
# NOTE: `-DevCmdArguments` are arguments to `vsdevcmd.bat`
# Select compiler
if ($Compiler -eq "MSVC") {
$_Compiler = "MSVC"
Set-Item -Path "env:CC" -Value "cl.exe"
Set-Item -Path "env:CXX" -Value "cl.exe"
}
elseif ($Compiler -eq "Clang") {
$_Compiler = "Clang"
Set-Item -Path "env:CC" -Value "clang-cl.exe"
Set-Item -Path "env:CXX" -Value "clang-cl.exe"
}
Write-Host "Selecting $_Compiler as C/C++ compiler."
Write-Host "======================================="
In fact, we have a simple and clean way to do it.
As we all know, the child shell launched in the shell automatically inherits the variables of the parent shell. Therefore, we only need to start CMD in PowerShell, execute vcvars64.bat, and start PowerShell again in this CMD.
For Visual Studio 2019:
cmd /K '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" && powershell.exe'
If you are using PowerShell Core:
cmd /K '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" && pwsh.exe'
You can wrap it as a function and put it in Powershell Profiles ($PSHOME\Microsoft.PowerShell_profile.ps1 for all users):
function vcvars64 {
cmd /K '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" && powershell.exe'
}
Or if you are using PowerShell Core:
function vcvars64 {
cmd /K '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" && pwsh.exe'
}
Then simply execute vcvars64 in PowerShell:
PS C:\Users\Glavo> cl
cl: The term 'cl' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
PS C:\Users\Glavo> vcvars64
**********************************************************************
** Visual Studio 2019 Developer Command Prompt v16.11.5
** Copyright (c) 2021 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'
PowerShell 7.1.5
Copyright (c) Microsoft Corporation.
https://aka.ms/powershell
Type 'help' to get help.
PS C:\Users\Glavo> cl
Microsoft (R) C/C++ Optimizing Compiler Version 19.29.30136 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
usage: cl [ option... ] filename... [ /link linkoption... ]
Instead of
Calling the Batch script
Writing the environment variables down
Performing modifications in so complicated a way, with Visual Studio 2022 (and probably 2019), you can use the following much more simpler approach
Import-Module "VS-Directory\Community\Common7\Tools\Microsoft.VisualStudio.DevShell.dll"
Enter-VsDevShell -VsInstallPath "VS-Directory\Community" -DevCmdArguments
If however, you wish to use 64 bit MSVC and environment by default for VS, you can use the DevCmdArguments with arch=64
Enter-VsDevShell -VsInstallPath "VS-Directory\Community" -DevCmdArguments '-arch=x64'
For someone who is still struggling with it in 2020 and Visual Studio Code 1.41.1, so this is a bit off-topic here.
Using all different parts of code from previous answers and the Internet, e.g., from How can I use vcvars64.bat from PowerShell? and with a step by step approach I managed to have the below script working.
Saved into Visual Studio Code "settings.json" and with the Code Runner extension installed.
With Microsoft (R) C/C++ Optimizing Compiler Version "cl.exe" from Visual Studio 2015/14.0:
"code-runner.runInTerminal": true,
"code-runner.executorMap": {
"cpp": "cd $dir; pushd \"C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\"; cmd.exe /c \"call vcvarsall.bat x86_amd64 & set > %temp%\\vcvars.txt\"; Get-Content \"$env:temp\\vcvars.txt\" | Foreach-Object { if ($_ -match \"^(.*?)=(.*)$\") { Set-Content \"env:\\$($matches[1])\" $matches[2] }}; popd; cls; cl *.cpp; .\\\"$fileNameWithoutExt.exe\"; Write-Host -NoNewLine 'Press any key to continue...'; $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown'); del \"$fileNameWithoutExt.exe\"; del \"$fileNameWithoutExt.obj\""}
With Microsoft (R) C/C++ Optimizing Compiler Version "cl.exe" from Visual Studio 2019/16.4.3:
"code-runner.runInTerminal": true,
"code-runner.executorMap": {
"cpp": "cd $dir; pushd \"c:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\"; cmd.exe /c \"call vcvarsall.bat x86_amd64 & set > %temp%\\vcvars.txt\"; Get-Content \"$env:temp\\vcvars.txt\" | Foreach-Object { if ($_ -match \"^(.*?)=(.*)$\") { Set-Content \"env:\\$($matches[1])\" $matches[2] }}; popd; cls; cl *.cpp; .\\\"$fileNameWithoutExt.exe\"; Write-Host -NoNewLine 'Press any key to continue...'; $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown'); del \"$fileNameWithoutExt.exe\"; del \"$fileNameWithoutExt.obj\""}
As an extension to Andy S's answer, this is updated for Visual Studio 2019 Community edition. However, I also needed 64-bit, so this includes the -arch=amd64 and -host_arch=amd64 flags as well for anyone that needs them.
pushd "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools"
cmd /c "VsDevCmd.bat -arch=amd64 -host_arch=amd64&set " |
foreach {
if ($_ -match "=") {
$v = $_.split("="); set-item -force -path "ENV:\$($v[0])" -value "$($v[1])"
}
}
popd
Write-Host "`nVisual Studio 2019 Command Prompt variables set." -ForegroundColor Yellow
Try powershell module posh-vsdev. It even seems to have support for multiple installed versions of Visual Studio.
Install-Module -Name posh-vsdev -Scope CurrentUser
# Import the posh-vsdev module module
Import-Module posh-vsdev
# Get all installed Visual Studio instances
Get-VisualStudioVersion
# Get a specific version
Get-VisualStudioVersion -Version 14
# Use the Developer Command Prompt Environment
Use-VisualStudioEnvironment
# Restore the non-Developer environment
Reset-VisualStudioEnvironment
# Reset cache of Visual Studio instances
Reset-VisualStudioVersionCache
# Add posh-vsdev to your PowerShell profile
Add-VisualStudioEnvironmentToProfile -UseEnvironment
I like to pass the commands into a child shell like so:
cmd /c "`"${env:VS140COMNTOOLS}vsvars32.bat`" && <someCommand>"
Or alternatively
cmd /c "`"${env:VS140COMNTOOLS}..\..\VC\vcvarsall.bat`" amd64 && <someCommand> && <someOtherCommand>"
First, check the contents of this folder:
C:/ProgramData/Microsoft/VisualStudio/Packages/_Instances/
There'll be another folder in it with a name consisting of hex digits (e.g. 2a7a9ed6, but that will vary for different MSVC versions). I'll refer to it as <instance_id>.
Then run from PowerShell:
Import-Module 'C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\Common7\Tools\Microsoft.VisualStudio.DevShell.dll'; Enter-VsDevShell <instance_id> -DevCmdArguments '-arch=x64'
Or you can create a shortcut with the following target:
<path to your powershell.exe> -noe -c "&{Import-Module """C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\Common7\Tools\Microsoft.VisualStudio.DevShell.dll"""; Enter-VsDevShell <instance_id> -DevCmdArguments '-arch=x64'}"
Obviously, drop -arch=x64 if you need the x86 toolset.
To start any latest PowerShell with dev tools env:
C:/Program Files/PowerShell/7/pwsh.exe -noe -c "&{Import-Module """C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools\Microsoft.VisualStudio.DevShell.dll"""; Enter-VsDevShell 5f8ef82b}"
If it doesn't work look for Developer PowerShell for VS 2019 via quick start menu search -> right-click properties -> copy target line -> change exe path to desired PowerShell.exe
Can also start it like that for your Editor/IDE of choice
Example for vscode:
"terminal.integrated.profiles.windows": {
"win_dev_shell_64": {
"path": "C:/Program Files/PowerShell/7/pwsh.exe",
"args": [
"-noe",
"-c",
"&{Import-Module \"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\Common7\\Tools\\Microsoft.VisualStudio.DevShell.dll\"; Enter-VsDevShell 5f8ef82b}"
]
}
},
"terminal.integrated.defaultProfile.windows": "win_dev_shell_64",
Related
I'm using powershell to try automating some build tools update/installation for visual studio 2022 build tools on our build agents. In the UI its these 3 options that I need:
sql server build tools
I exported the config from the first server where I had installed this by hand, so I could get the IDs of the items to install:
{
"version": "1.0",
"components": [
"Microsoft.VisualStudio.Component.Roslyn.Compiler",
"Microsoft.Component.MSBuild",
"Microsoft.VisualStudio.Component.CoreBuildTools",
"Microsoft.VisualStudio.Workload.MSBuildTools",
"Microsoft.Net.Component.4.7.2.TargetingPack",
"Microsoft.Net.Component.4.8.TargetingPack",
"Microsoft.VisualStudio.Component.SQL.SSDTBuildSku"
]
}
I used the 3 sku's at the bottom to create the script to try and install it:
$components =#(
"Microsoft.Net.Component.4.7.2.TargetingPack",
"Microsoft.Net.Component.4.8.TargetingPack",
"Microsoft.VisualStudio.Component.SQL.SSDTBuildSku")
$components | %{Start-Process "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vs_installer.exe" -ArgumentList 'modify --installPath "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools" --passive --add $_' -Wait -PassThru}
This I know comes with a prompt for reboot through the UI, but I have rebooted post install and it doesn't show that these have been installed. I don't get any sort of confirmation that it was success or fail other than this output, though I do see the UI pop up briefly because i didn't specify silent:
script output
what have I done wrong?
Swap the quotes in your -ArgumentList to outer double, and inner single. Interpolation doesn't occur inside single quotes so $_ isn't being expanded.
$components =#(
"Microsoft.Net.Component.4.7.2.TargetingPack",
"Microsoft.Net.Component.4.8.TargetingPack",
"Microsoft.VisualStudio.Component.SQL.SSDTBuildSku")
$components | %{Start-Process "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vs_installer.exe" -ArgumentList "modify --installPath 'C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools' --passive --add $_" -Wait -PassThru}
following what Metzli_Tonaltzintli said, I tried something else and encased the download location in double-quotes and escaped it.
$components =#(
"Microsoft.Net.Component.4.7.2.TargetingPack",
"Microsoft.Net.Component.4.8.TargetingPack",
"Microsoft.VisualStudio.Component.SQL.SSDTBuildSku")
$installTo = "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools"
$components | %{Start-Process "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vs_installer.exe" -ArgumentList "modify --installPath `"$installTo`" --passive --add $_" -Wait -PassThru}
The moment I did this the UI popped up and actually shows a download status and reboots immediately after.
A Visual Studio project can be upgraded from the command line using the devenv.exe command as follows:
devenv.exe SOLUTION_PATH /Upgrade
Where SOLUTION_PATH is a path to a Visual Studio solution (or project) file.
What is the most direct way to perform this step as part of a GitHub action?
What I Have Tried
So far I have failed to find a way to get devenv.exe into the path of the GitHub Action. There does not appear to be a prebuilt action step for this (setup-msbuild step does not make devenv available). Even hardcoding a path such as
MSDEVENV_PATH: ${{'C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\devenv.com'}}
... then later ...
run: ${{env.MSDEVENV_PATH}} ${{env.SOLUTION_FILE_PATH}} /Upgrade
fails because the path contains spaces, and I can find no way to add quotation marks.
I am aware of a way to find devenv using powershell and extra downloadable packages however this will require writing a PowerShell script, and presumably signing it, and I have no idea whether this will even work in a GitHub Action. Perhaps there is a much simpler approach, hence my question: what is the most direct way to upgrade a solution?
You need a Windows-based runner. vswhere is the tool to get path to various components of the Visual Studio installation and its folder is in the path (source).
run: |
$devenv = & vswhere.exe '-property' productPath
Start-Process -FilePath $devenv -ArgumentList '${{env.SOLUTION_FILE_PATH}} /Upgrade' -Wait
Thanks to #riQQ's partial answer I currently have the following, which waits for the output to be done using both a pipe to Out-Null suggested in this answer and also waits for the generated files to appear. Note that I am using a path to the project not to the solution. (I could not get solution upgrading to work correctly, although I never worked out why.)
run: |
$devenv = & vswhere.exe '-property' productPath
Write-Output "$devenv"
& $devenv "${{env.VCPROJ_FILE_PATH}}" /Upgrade /NoSplash | Out-Null
Write-Output "devenv launched"
while (!(Test-Path "${{env.VCXPROJ_FILE_PATH}}")) { Start-Sleep -Seconds 10 }
Write-Output "vcxproj found"
while (!(Test-Path "${{env.VCXPROJ_FILTERS_FILE_PATH}}")) { Start-Sleep -Seconds 10 }
Write-Output "vcxproj.filters found"
Start-Sleep -Seconds 10
Write-Output "done."
For some reason this step is taking over 5 minutes to complete when run as part of a GitHub Action. It takes only a few seconds on my local machine. Because of the nasty file polling I don't consider this an ideal solution, but I am posting it here for reference.
I am unable to use the cl command in PowerShell.
I tried to add the following command to my PowerShell profile to exec vcbuildtools.bat, but PowerShell does not recognize cl command on PowerShell?
&"C:\Program Files (x86)\Microsoft Visual C++ Build Tools\vcbuildtools.bat"
OS: Windows 10
Just to be clear I'm addressing the asker's issue that cl is not in the PATH even after running this in PowerShell
&"C:\Program Files (x86)\Microsoft Visual C++ Build Tools\vcbuildtools.bat"
I think this boils down to the issue that batch file can't export variables to PowerShell (also related: this question), as you've found out with vcbuildtools.bat. I think it's because PowerShell invokes a cmd.exe subshell to execute the batch file which changes the environment in the subshell but the changes don't propagate to the parent shell i.e. PowerShell.
Solution 1
One way is to use the fact that subshell inherits the environment from the parent shell. So if you run this in PowerShell, the environment set by the batch file is preserved
cmd.exe /k "C:\Program Files (x86)\Microsoft Visual C++ Build Tools\vcbuildtools.bat" `& powershell
Take note of `&. The character has to be escaped because it has a special meaning in PowerShell.
Solution 2
The Pscx module has an Import-VisualStudioVars function which imports environment variables for Visual Studio. An example usage is
Import-VisualStudioVars 2015 amd64
if you're using VS/BuildTools 2015 and compiling 64-bit programs. You can use Pop-EnvironmentBlock to revert the changes. See man Import-VisualStudioVars -full for more information.
Alternatively, Pscx also has an Invoke-BatchFile function that retains environment changes by a batch file. An example usage
Invoke-BatchFile "C:\Program Files (x86)\Microsoft Visual C++ Build Tools\vcbuildtools.bat"
See man Invoke-Batchfile -full for more information.
Notes
To download the up-to-date version of Pscx from PowerShell gallery, you will need PowerShellGet which is shipped with PowerShell 5 and is available as a downloadable installer for PowerShell 3 and 4.
For those with PowerShell 1 and 2, older versions of Pscx is available on Codeplex.
You can use the following function to invoke a cmd.exe shell script (batch file) and persist its environment variables:
function Invoke-CmdScript {
param(
[String] $scriptName
)
$cmdLine = """$scriptName"" $args & set"
& $env:SystemRoot\system32\cmd.exe /c $cmdLine |
Select-String '^([^=]*)=(.*)$' | ForEach-Object {
$varName = $_.Matches[0].Groups[1].Value
$varValue = $_.Matches[0].Groups[2].Value
Set-Item Env:$varName $varValue
}
}
Add this function to your PowerShell profile, and run the batch file using the function:
Invoke-CmdScript "C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\vsvars32.bat"
Fortunately, VS 2019 Community now has a Developer PowerShell for VS 2019 command.
The actual command, if you want to see the properties for the shortcut, is rather verbose.
C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -noe -c "&{Import-Module """C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools\Microsoft.VisualStudio.DevShell.dll"""; Enter-VsDevShell 14bbfab9}"
Anyway, I am using this and it adds the right cl.exe to my path, but there is an odd message after running it:
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.23.28105\include\ostream(750): warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
.\hey.cpp(4): note: see reference to function template instantiation 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const char *)' being compiled
Another option from PowerShell gallery:
posh-vs
Makes Visual Studio command line tools available in PowerShell. Supports Visual Studio 2017 and 2015.
I also encountered the same problem, type cmd.exe and you'll change control to command line.
PowerShell example
If you want to go back to PowerShell, no problem. Just write exit. As simple as it sounds
I am trying to compile my arith.idl file with midl. I am running windows 7 pro.
Here is the command I launch in a powershell prompt:
PS> 'C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\midl.exe' .\arith.idl
Microsoft (R) 32b/64b MIDL Compiler Version 7.00.0555
Copyright (c) Microsoft Corporation. All rights reserved.
64 bit Processing .\arith.idl
midl : command line error MIDL1005 : cannot find C preprocessor cl.exe
PS>
I am quite a noob at windows RPC programming, I would highly appreciate some help. I have read this but this does not resolve anything (same symptoms). I have also tried specifying the preprocessor cl.exe with this command:
PS C:\> & 'C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\midl.exe' /cpp_cmd 'C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\cl.exe' C:\Users\$e\Desktop\MIDL\arith.idl
Microsoft (R) 32b/64b MIDL Compiler Version 7.00.0555
Copyright (c) Microsoft Corporation. All rights reserved.
Processing C:\Users\philippe.CHIBOLLO\Desktop\MIDL\arith.idl
PS C:\>
This command does not return anything and
echo $?
returns False
EDIT:
The execution of the vcvarsall.bat file does not change anything. Here is the output of the powershell command I launched:
PS C:\> & 'C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat'
Setting environment for using Microsoft Visual Studio 2010 x86 tools.
PS C:\> & 'C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\midl.exe' /cpp_cmd 'C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\cl.exe' C:\Users\$me\Desktop\MIDL\arith.idl
Microsoft (R) 32b/64b MIDL Compiler Version 7.00.0555
Copyright (c) Microsoft Corporation. All rights reserved.
Processing C:\Users\$me\Desktop\MIDL\arith.idl
PS C:\> echo $?
False
PS C:\>
I wrote an article about this not too long ago. When you run a Cmd.exe shell script (batch file) from PowerShell, environment variable changes do not propagate to the parent process (PowerShell). To work around this, you need to capture the environment variable changes after the shell script completes. The article is this one:
IT Pro Today: Take Charge of Environment Variables in PowerShell
You can use the Invoke-CmdScript function from that article to run vcvarsall.bat and propagate its environment variable changes to PowerShell.
Invoke-CmdScript looks like this:
function Invoke-CmdScript {
param(
[String] $scriptName
)
$cmdLine = """$scriptName"" $args & set"
& $Env:SystemRoot\system32\cmd.exe /c $cmdLine |
select-string '^([^=]*)=(.*)$' | foreach-object {
$varName = $_.Matches[0].Groups[1].Value
$varValue = $_.Matches[0].Groups[2].Value
set-item Env:$varName $varValue
}
}
You can also use the Get-Environment and Restore-Environment functions from that article if you want to localize the environment variable changes in your PowerShell script.
In a serious intiative to migrate all my command line operations to PowerShell, I would like to avoid using the old fashioned command console for anything. However, the Visual Studio Command prompt has various environment variables and path settings not found in the default command prompt. How could I create a 'Visual Studio PowerShell' with those same settings?
You can use for example this script to import Visual Studio command prompt environment, see the examples in the script documentation comments, e.g. for Visual Studio 2010:
Invoke-Environment '"%VS100COMNTOOLS%\vsvars32.bat"'
Having done that in the beginning of a PowerShell session (from your profile or manually), you get what you ask for in this PowerShell session.
Or you can use the solution provided by Keith Hill in this answer.
have a look at PowerConsole
PowerConsole has been incorporated into NuGet http://nuget.codeplex.com/. You get PowerShell inside Visual Studio and a package management system.
I use this script that I call Initialize-VisualStudio.ps1, i call it in my profile with dot source, to set the environment variables need it, in my actual session:
param([switch]$ArquitectureX86)
if($ArquitectureX86)
{ $arq= "x86"}
else
{ $arq="x64"}
pushd 'c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC'
cmd /c "vcvarsall.bat $arq&set" |
foreach {
if ($_ -match "=") {
$v = $_.split("="); set-item -force -path "ENV:\$($v[0])" -value "$($v[1])";
}
}
popd
What I do is create a simple cmd batch command script that looks like this:
call "%VS80COMNTOOLS%vsvars32.bat"
powershell
Then I create a shortcut that invokes this through cmd. The shortcut target looks like:
%windir%\System32\cmd.exe /k "SetupPSBuildEnvironment.cmd"
If you want the console to look like the powershell console, just modify the Layout to your liking in the shortcut properties.
First, check the contents of this folder:
C:/ProgramData/Microsoft/VisualStudio/Packages/_Instances/
There'll be another folder in it with a name consisting of hex digits (e.g. 2a7a9ed6, but that will vary for different MSVC versions). I'll refer to it as <instance_id>.
Then run from PS:
Import-Module 'C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\Common7\Tools\Microsoft.VisualStudio.DevShell.dll'; Enter-VsDevShell <instance_id> -DevCmdArguments '-arch=x64'
Or you can create a shortcut with the following target:
<path to your powershell.exe> -noe -c "&{Import-Module """C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\Common7\Tools\Microsoft.VisualStudio.DevShell.dll"""; Enter-VsDevShell <instance_id> -DevCmdArguments '-arch=x64'}"
Obviously, drop -arch=x64 if you need x86 toolset.
Works for me on Windows 10 with MS Build Tools 16.9.5 and PowerShell 5.1.19041,7.1.3