【问题标题】:How can I use PowerShell with the Visual Studio Command Prompt?如何将 PowerShell 与 Visual Studio 命令提示符一起使用?
【发布时间】:2011-01-08 15:30:48
【问题描述】:

我使用 Beta 2 已经有一段时间了,在运行 Visual Studio 2010 命令提示符时,我不得不使用 cmd.exe 让我发疯。我曾经为 Visual Studio 2008 提供了一个不错的 vsvars2008.ps1 脚本。是否有 vsvars2010.ps1 脚本或类似的脚本?

【问题讨论】:

    标签: visual-studio-2010 visual-studio powershell


    【解决方案1】:

    从博客文章中大量窃取 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 不再存在。相反,您可以使用 vsvars32.bat 文件,该文件位于 Common7\Tools 文件夹中。

    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
    

    你也可以让split只创建两个item,避免破坏值,包括等号,也是环境变量名和值的分隔符:

    $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
    

    【讨论】:

    • 请注意,同样的技术也适用于 Visual Studio 2012。只需将“Microsoft Visual Studio 10.0”更改为“Microsoft Visual Studio 11.0”
    • echo $Profile 查看您的 profile.ps1 的预期路径(如果您从未创建过它)
    • 脚本本身运行良好。不过需要注意的是(可能):由于 Visual Studio 中的包管理器控制台本身就是一个 PowerShell 主机,因此该脚本也将在那里运行。这似乎不是问题,除非您注意到“在没有调试的情况下运行”或任何其他运行启动标准 Windows 控制台的功能或插件在 PMC 初始化后将不起作用。我解决了这个问题,而不是将这个答案中的脚本保存到“profile.ps1”,而是将它保存到“Microsoft.PowerShell_profile.ps1”,以便它只能在“正确的”PowerShell会话中运行。
    • 当有完美的环境变量(VS2015 的 VS140COMNTOOLS)可供使用时,硬编码路径是非常糟糕的做法。这甚至适用于自定义 VS 安装。
    • 我很欣赏使用环境变量的愿望,但这些变量似乎是由我们试图从中提取变量的批处理文件初始化的。我很乐意看到相反的证据。在执行 VsDevCmd.bat 之前,我有一个干净的 Windows 10 安装和一个干净的 Visual Studio 2017 安装,并且没有 VS150COMNTOOLS 环境变量。
    【解决方案2】:

    最简单的选择是运行 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 Community Extensions 2.0 版本中提供。

    【讨论】:

      【解决方案3】:

      我找到了一个简单的方法here:修改快捷方式。

      原来的快捷方式是这样的:

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

      在最后一个引号之前添加 &amp; powershell,如下所示:

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

      如果您想让它看起来更像 PowerShell,请转到快捷方式属性的 Colors 选项卡,并将 Red、Green 和 Blue 值分别设置为 1、36 和 86。

      【讨论】:

      • 直截了当,工作起来就像一个魅力。这个答案值得更多的支持。
      • 我唯一不喜欢的是,它会加载一个冗余的 cmd.exe 进程。除此之外,这是一个不错的解决方案。
      【解决方案4】:

      为了 (a) 提供 Visual Studio 2013 支持; (b) 结合前两个答案中最好的一个; (c) 提供一个函数包装器:

      这建立在Andy's technique 的基础上(它建立在艾伦麦克的技术之上,正如安迪所指出的那样(这反过来又建立在罗伯特安德森的技术之上,正如艾伦所指出的那样(所有这些都有一个轻微的故障,正如用户在本页上所指出的那样,仅称为“我——”,所以我也考虑到了)))。

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

      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, ...
      • 不错,但如果没有 pushd/popd,imo 会更好。只需使用类似cmd /c """$targetDir\vcvarsall.bat""&amp;set"
      【解决方案5】:

      Keith has already mentioned PowerShell 社区扩展 (PSCX),及其 Invoke-BatchFile 命令:

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

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

      Import-VisualStudioVars -VisualStudioVersion 2013
      

      【讨论】:

      • 从 PSCX 3.2.0 开始,此 cmdlet 不支持 VS 2015。我为它开了一个issue
      【解决方案6】:

      Andy S for his answer 致敬。我一直在使用他的解决方案,但今天遇到了问题。任何包含等号的值都会在等号处被截断。例如,我有:

      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 versions 更新它?这是谷歌的第一个结果,我认为你的添加会对人们有所帮助。
      【解决方案7】:

      代替

      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 和环境,您可以使用带有 arch=64 的 DevCmdArguments

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

      【讨论】:

        【解决方案8】:

        使用“模块”和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 "======================================="
        

        【讨论】:

          【解决方案9】:

          对于那些在 2020 年和 Visual Studio Code 1.41.1 中仍在苦苦挣扎的人,所以这里有点离题了。

          使用来自先前答案和 Internet 的所有不同代码部分,例如来自 How can I use vcvars64.bat from PowerShell? 的代码,并通过逐步的方法,我设法使以下脚本正常工作。

          保存到 Visual Studio Code“settings.json”并安装了 Code Runner 扩展。

          使用来自 Visual Studio 2015/14.0 的 Microsoft (R) C/C++ 优化编译器版本“cl.exe”:

          "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\""}
          

          使用来自 Visual Studio 2019/16.4.3 的 Microsoft (R) C/C++ 优化编译器版本“cl.exe”:

          "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\""}
          

          【讨论】:

          • 为什么C++编译器进图?
          • @彼得莫滕森带有属性。
          【解决方案10】:

          作为Andy S's answer 的扩展,它已针对 Visual Studio 2019 社区版进行了更新。但是,我还需要 64 位,因此这包括 -arch=amd64-host_arch=amd64 标志以及任何需要它们的人。

          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
          

          【讨论】:

            【解决方案11】:

            事实上,我们有一个简单而干净的方法来做到这一点。

            众所周知,在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 Profiles(所有用户为$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... ]
            

            【讨论】:

              【解决方案12】:

              试试 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
              

              【讨论】:

                【解决方案13】:

                我喜欢像这样将命令传递到子 shell:

                cmd /c "`"${env:VS140COMNTOOLS}vsvars32.bat`" && <someCommand>"
                

                或者

                cmd /c "`"${env:VS140COMNTOOLS}..\..\VC\vcvarsall.bat`" amd64 && <someCommand> && <someOtherCommand>"  
                

                【讨论】:

                • 为什么?是什么原因?它有什么优点?请通过editing (changing) your answer 回复,而不是在 cmets 中(without "Edit:"、"Update:" 或类似的 - 答案应该看起来像是今天写的)。
                • 对不起@PeterMortensen,我不记得为什么上述的hijinks 是必要的,或者为什么我更喜欢它们而不是替代方案。当我看到这个时,我唯一能想到的就是我应该早点切换到 vim。
                【解决方案14】:

                首先,检查这个文件夹的内容:

                C:/ProgramData/Microsoft/VisualStudio/Packages/_Instances/
                

                其中会有另一个文件夹,其名称由十六进制数字组成(例如 2a7a9ed6,但会因不同的 MSVC 版本而有所不同)。我将其称为&lt;instance_id&gt;

                然后从 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'
                

                或者您可以使用以下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'}"
                

                显然,如果您需要 x86 工具集,请放弃 -arch=x64

                【讨论】:

                  猜你喜欢
                  • 2011-05-22
                  • 2010-11-10
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2018-06-18
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多