Как я могу использовать PowerShell с командной строкой Visual Studio?

119

Я уже некоторое время использую Beta 2, и меня сводит с ума то, что мне приходится использовать cmd.exe при запуске командной строки VS2010. Раньше у меня был хороший сценарий vsvars2008.ps1 для Visual Studio 2008. У кого-нибудь есть vsvars2010.ps1 или что-то подобное?

Энди С
источник

Ответы:

223

Обильно воровав отсюда: http://allen-mack.blogspot.com/2008/03/replace-visual-studio-command-prompt.html , я смог заставить это работать. Я добавил в свой 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
Энди С
источник
6
Замечу, что этот же метод работает и для Visual Studio 2012. Просто замените «Microsoft Visual Studio 10.0» на «Microsoft Visual Studio 11.0»
Энди С.
9
echo $Profileчтобы увидеть предполагаемый путь для вашего profile.ps1, если вы никогда его не создавали
Мэтт Стивенсон
5
Сам скрипт прекрасно работает. Тем не менее, предостережение (возможно): поскольку консоль диспетчера пакетов в Visual Studio сама является хостом PowerShell, этот сценарий также будет запускаться там. Кажется, это не проблема, пока вы не заметите, что «Запуск без отладки» или любые другие функции или плагины, запускающие стандартную консоль Windows, не будут работать после инициализации PMC. Я работал над этим, вместо того, чтобы сохранять сценарий в этом ответе на «profile.ps1», я сохранил его в «Microsoft.PowerShell_profile.ps1», чтобы он запускался только в «правильном» сеансе PowerShell.
Крис Симмонс,
3
Жесткое кодирование путей, когда есть прекрасные переменные среды (VS140COMNTOOLS для VS2015), действительно плохая практика. Это будет работать даже для пользовательских установок VS.
Voo
5
Я ценю желание использовать переменные среды, но эти переменные, похоже, инициализируются тем самым командным файлом, из которого мы пытаемся извлечь переменные. Я был бы рад увидеть доказательства обратного. У меня чистая установка Windows 10 с чистой установкой Visual Studio 2017 и без переменной среды VS150COMNTOOLS, пока я не запустил VsDevCmd.bat.
Andy S
26

Самый простой вариант - запустить командную строку VS 2010, а затем запустить PowerShell.exe. Если вы действительно хотите сделать это из «домашней» командной строки PowerShell, то показанный вами подход - лучший вариант. Я использую сценарий, который написал недавно Ли Холмс:

<#
.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, который скоро появится.

Кейт Хилл
источник
22

Я нашел простой способ здесь : изменить ярлык.

Исходный ярлык выглядит примерно так:

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

Если вы хотите сделать его более похожим на PS, перейдите на вкладку « Цвета » в свойствах ярлыка и установите для красного, зеленого и синего значения 1, 36 и 86 соответственно.

Скриншот

user247702
источник
Простой и работает как шарм. Этот ответ заслуживает большего количества голосов.
Марк Меуэр
2
Единственное, что мне не нравится в этом, так это то, что он сохраняет загруженным избыточный процесс cmd.exe. В остальном это хорошее решение.
orad 06
17

Старый вопрос, но на него стоит еще один ответ: (а) обеспечить поддержку VS2013; (б) объединить лучшее из двух предыдущих ответов; и (c) предоставить оболочку функции.

Это основано на методе @ 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
    }
    pushd $targetDir
    cmd /c "vcvarsall.bat&set" |
    foreach {
      if ($_ -match "(.*?)=(.*)") {
        Set-Item -force -path "ENV:\$($matches[1])" -value "$($matches[2])"
      }
    }
    popd
    write-host "`nVisual Studio $version Command Prompt variables set." -ForegroundColor Yellow
}
Майкл Соренс
источник
Для совместимости с PowerShell 2.0 в разделе параметров требуется [parameter(Mandatory=$true,...
sakra
1
Красиво, но было бы лучше без pushd / popd. Просто используйте что-нибудь вродеcmd /c """$targetDir\vcvarsall.bat""&set"
stijn
9

Кейт уже упоминал о расширениях сообщества PowerShell (PSCX) со своей Invoke-BatchFileкомандой:

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

Я также заметил, что PSCX также имеет Import-VisualStudioVarsфункцию:

Import-VisualStudioVars -VisualStudioVersion 2013
Тахир Хассан
источник
4
Начиная с PSCX 3.2.0, VS 2015 не поддерживается в этом командлете. Я открыл для этого вопрос .
orad 06
3

Престижность Энди С. за его ответ. Некоторое время я использовал его решение, но сегодня столкнулся с проблемой. Любое значение, имеющее знак равенства, обрезается до знака равенства. Например, у меня было:

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

Но мой сеанс PS сообщил:

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 ? Это первый результат гугла, думаю ваше дополнение людям поможет.
Squirrelkiller
1

Для тех, кто все еще борется с этим в 2020 году и Visual Studio Code 1.41.1, поэтому здесь немного не по теме.

Используя все разные части кода сверху и из Интернета, например, из https://help.appveyor.com/discussions/questions/18777-how-to-use-vcvars64bat-from-powershell и с пошаговым подходом, мне удалось работайте с приведенным ниже сценарием.

Сохраняется в VSCode "settings.json" с установленным расширением Code Runner.

С версией оптимизирующего компилятора Microsoft (R) C / C ++ "cl.exe" из 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\""}

С версией оптимизирующего компилятора Microsoft (R) C / C ++ "cl.exe" из 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\""}

НТН

olin000
источник
0

Мне нравится передавать команды в дочернюю оболочку следующим образом:

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

Или альтернативно

cmd /c "`"${env:VS140COMNTOOLS}..\..\VC\vcvarsall.bat`" amd64 && <someCommand> && <someOtherCommand>"  
MatrixManAtYrService
источник