我该如何在Visual Studio命令提示符中使用PowerShell?

141

我已经使用Beta 2有一段时间了,每当运行Visual Studio 2010命令提示符时,我不得不转到cmd.exe,这让我感到非常烦恼。我曾经有一个很好的vsvars2008.ps1脚本适用于Visual Studio 2008。是否有类似的vsvars2010.ps1脚本呢?


1
截至Visual Studio 2022,已经有一个专门的快捷方式来设置PowerShell进行开发。在Windows 11上,包含VS 2022的Cmd和PowerShell快捷方式的目录的默认路径为C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Visual Studio 2022\Visual Studio Tools。注意:默认情况下,该快捷方式会打开Windows PowerShell(即版本5.1),但可以轻松更改为pwsh.exe以使用最新和最好的PowerShell 7 - informatik01
1
现在有一个维基[启动开发人员命令提示符](https://github.com/Microsoft/vswhere/wiki/Start-Developer-Command-Prompt) - malat
这是现在最好的答案! - fig
现在有一个可安装的Powershell模块,可以自动化设置所需的环境变量,它被称为posh-vs - mhdadk
现在有一个可安装的Powershell模块,可以自动化设置所需的环境变量,它被称为posh-vs - undefined
15个回答

249

借鉴博客文章Replace Visual Studio Command Prompt with PowerShell的思路,我成功地实现了这个功能。我在我的profile.ps1文件中添加了以下内容,一切正常。

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

这个方法已经使用多年非常成功 - 直到 Visual Studio 2015。 vcvarsall.bat 不再存在。相反,您可以使用位于 Common7\Tools 文件夹中的 vsvars32.bat 文件。

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

Visual Studio 2017的情况又有所变化。vsvars32.bat似乎已被VsDevCmd.bat取代。具体路径可能因您使用的Visual Studio 2017版本而异。

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

您还可以使拆分仅创建两个项目,以避免破坏包含等号的值,该等号也是环境变量名称和值的分隔符:

$v = $_.split("=", 2); set-item -force -path "ENV:\$($v[0])"  -value 

现在 Visual Studio 2022 已经是64位了,因此进行了一些小的变化。

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

6
请注意,这种技术同样适用于Visual Studio 2012。只需将“Microsoft Visual Studio 10.0”更改为“Microsoft Visual Studio 11.0”。 - Andy S
11
输入 echo $Profile 命令,以查看您的 profile.ps1 文件的路径,如果您从未创建过该文件。 - Matt Stephenson
5
脚本本身运行良好。然而需要注意的是(可能):由于Visual Studio中的包管理器控制台本身就是PowerShell主机,因此该脚本也将在那里运行。这似乎不是问题,直到你注意到“无调试运行”或任何其他启动标准Windows控制台的函数或插件在 PMC 初始化后无法正常工作。我通过将脚本保存为“Microsoft.PowerShell_profile.ps1”而不是“profile.ps1”,以便只在“正确”的PowerShell会话中运行来解决这个问题。 - Chris Simmons
3
如果有完全正常的环境变量可供使用(如VS140COMNTOOLS用于VS2015),硬编码路径是非常糟糕的做法。这甚至适用于自定义的VS安装。 - Voo
8
我理解您希望使用环境变量的愿望,但是这些变量似乎是由我们试图从中提取变量的批处理文件初始化的。如果有相反的证据,我会很高兴看到。我在干净的Windows 10安装中执行了干净的Visual Studio 2017安装,并且没有VS150COMNTOOLS环境变量,直到我执行VsDevCmd.bat。 - Andy S
显示剩余9条评论

30

最简单的方法是运行VS 2010命令提示符,然后启动PowerShell.exe。如果你真的想从你的“主页”PowerShell提示符中执行此操作,那么你展示的方法就是正确的方式。我使用了Lee Holmes写的一段脚本:

<#
.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
}

注意:该函数将在不久的将来发布的基于模块的PowerShell社区扩展2.0版本中提供。


27

我在这里找到了一个简单的方法(链接已提供):修改快捷方式。

原始的快捷方式看起来像这样:

%comspec% /k ""C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\VsDevCmd.bat""

在最后一个引号前加上&powershell,就像这样:

%comspec% /k ""C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\VsDevCmd.bat" & powershell"
如果您想使其看起来更像PowerShell,请转到快捷方式属性的“颜色”选项卡,并将红色、绿色和蓝色的值分别设置为1、36和86。

直截了当,功能完美。这个答案值得更多的点赞。 - Mark Meuer
2
我唯一不喜欢的是它会保留一个多余的cmd.exe进程。除此之外,这是一个不错的解决方案。 - orad

17

为(a)提供Visual Studio 2013支持;(b)结合两个先前答案的优点;以及(c)提供一个函数包装器:

这是基于Andy的技术(Andy指出这建立在Allen Mack的技术基础上(而Allen又指出这又建立在Robert Anderson的技术基础上,正如所有这些技术都由仅被称为“me--”的用户在本页面中指出的那样有一个小故障,所以我也考虑到了这一点))。

这是我的最终代码 - 请注意在正则表达式中使用非贪婪量词来处理值中可能嵌入的任何等号。这也恰好简化了代码:与Andy的示例中的匹配然后拆分或与“me--”示例中的匹配然后indexof和子字符串不同,只需要单个匹配。

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
}

为了与PowerShell 2.0兼容,param部分需要[parameter(Mandatory=$true,... - sakra
1
不错,但我认为如果没有pushd/popd会更好。只需使用类似于cmd /c """$targetDir\vcvarsall.bat""&set"的东西即可。 - stijn

9

Keith已经提到 PowerShell社区扩展(PSCX),其中包含Invoke-BatchFile命令:

Invoke-BatchFile "${env:ProgramFiles(x86)}\Microsoft Visual Studio 12.0\VC\vcvarsall.bat"

我还注意到PSCX还有一个Import-VisualStudioVars函数:
Import-VisualStudioVars -VisualStudioVersion 2013

5
截至 PSCX 3.2.0 版本,此命令不支持 VS 2015。我已经为此打开了一个问题。链接 - orad

4

使用“模块”和VsDevShell更加简单、清晰。下面是适用于 MSVC 和 Clang 的简单 Powershell 脚本:

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 "======================================="

4

不需要

  1. 调用批处理脚本
  2. 把环境变量写下来
  3. 以更简单的方式进行修改,使用Visual Studio 2022(可能也适用于2019),可以采用以下方法
Import-Module "VS-Directory\Community\Common7\Tools\Microsoft.VisualStudio.DevShell.dll"
Enter-VsDevShell -VsInstallPath "VS-Directory\Community" -DevCmdArguments

如果您希望默认情况下在VS中使用64位MSVC和环境,则可以使用DevCmdArguments与arch=64。

Enter-VsDevShell -VsInstallPath "VS-Directory\Community" -DevCmdArguments '-arch=x64'

3

Andy S的答案致敬。我已经使用他的解决方案一段时间了,但今天我遇到了一个问题。任何带有等号的值都会在等号处截断。例如,我有:

JAVA_TOOL_OPTIONS=-Duser.home=C:\Users\Me

但是我的PowerShell会话报告如下:
PS C:\> $env:JAVA_TOOL_OPTIONS

-Duser.home

我通过修改我的个人资料脚本来解决了这个问题,具体修改如下:
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

嘿,很好的补充。也能更新一下VS2015/17版本吗?这是第一个Google搜索结果,我认为您的补充会帮助到大家。 - Squirrelkiller

3
事实上,我们有一种简单干净的方法来完成它。众所周知,自动在shell中启动的子shell会继承父shell的变量。因此,我们只需要在PowerShell中启动CMD,执行vcvars64.bat,然后再在这个CMD中启动PowerShell即可。
对于Visual Studio 2019:
cmd /K '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" && powershell.exe'

如果您正在使用PowerShell Core:
cmd /K '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" && pwsh.exe'

您可以将其包装为一个函数,并将其放入Powershell个人配置文件$PSHOME\Microsoft.PowerShell_profile.ps1适用于所有用户):

function vcvars64 {
  cmd /K '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" && powershell.exe'
}

如果您使用的是PowerShell Core:

function vcvars64 {
  cmd /K '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" && pwsh.exe'
}

然后在 PowerShell 中执行 vcvars64 命令:

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... ]

2
尝试使用 PowerShell 模块 posh-vsdev。它甚至似乎支持安装了多个版本的 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

1
还有posh-vs,它似乎更简单易用。 - mhdadk
1
还有posh-vs,它似乎更简单易用。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接