¿Cómo puedo usar PowerShell con el símbolo del sistema de Visual Studio?

119

He estado usando Beta 2 por un tiempo y me ha estado volviendo loco tener que apuntar a cmd.exe cuando ejecuto el símbolo del sistema VS2010. Solía ​​tener un buen script vsvars2008.ps1 para Visual Studio 2008. ¿Alguien tiene un vsvars2010.ps1 o algo similar?

Andy S
fuente

Respuestas:

223

Robando generosamente desde aquí: http://allen-mack.blogspot.com/2008/03/replace-visual-studio-command-prompt.html , pude hacer que esto funcionara. Agregué lo siguiente a mi profile.ps1 y todo está bien en el mundo.

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

Esto ha funcionado bien durante años, hasta Visual Studio 2015. vcvarsall.bat ya no existe. En su lugar, puede utilizar el archivo vsvars32.bat, que se encuentra en la carpeta 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

Las cosas han cambiado una vez más para Visual Studio 2017. vsvars32.batParece que se ha dejado de lado VsDevCmd.bat. La ruta exacta puede variar según la edición de Visual Studio 2017 que esté usando.

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
Andy S
fuente
6
Solo una nota rápida de que esta misma técnica funciona para Visual Studio 2012. Simplemente cambie "Microsoft Visual Studio 10.0" a "Microsoft Visual Studio 11.0"
Andy S
9
echo $Profilepara ver la ruta prevista para su profile.ps1, si nunca la ha creado
Matt Stephenson
5
El guión en sí funciona de maravilla. Sin embargo, una nota de precaución (posiblemente): como la Consola del Administrador de paquetes en Visual Studio es en sí misma un host de PowerShell, este script también se ejecutará allí. Esto no parece ser un problema hasta que observe que "Ejecutar sin depurar" o cualquier otra función o complemento que ejecute una consola estándar de Windows no funcionará después de que se inicialice el PMC. Trabajé alrededor de esto, en lugar de guardar el script en esta respuesta en "profile.ps1", lo guardé en "Microsoft.PowerShell_profile.ps1" para que solo se ejecute en una sesión de PowerShell "adecuada".
Chris Simmons
3
Es realmente una mala práctica codificar las rutas cuando hay variables de entorno perfectamente correctas (VS140COMNTOOLS para VS2015) para usar. Eso incluso funcionará para instalaciones VS personalizadas.
Voo
5
Aprecio el deseo de usar variables de entorno, pero esas variables parecen ser inicializadas por el mismo archivo por lotes del que estamos tratando de extraer variables. Me alegraría ver pruebas de lo contrario. Tengo una instalación limpia de Windows 10 con una instalación limpia de Visual Studio 2017 y ninguna variable de entorno VS150COMNTOOLS hasta que ejecuto VsDevCmd.bat.
Andy S
26

La opción más sencilla es ejecutar el símbolo del sistema de VS 2010 y luego iniciar PowerShell.exe. Si realmente desea hacer esto desde el indicador de PowerShell de su "inicio", el enfoque que muestra es el camino a seguir. Utilizo un guión que Lee Holmes escribió hace un tiempo:

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

Nota: esta función estará disponible en la versión basada en el módulo PowerShell Community Extensions 2.0 próximamente.

Keith Hill
fuente
22

Encontré un método simple aquí : modificar el acceso directo.

El atajo original es algo como esto:

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

Agregue & powershellantes de la última cita, así:

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

Si desea que se parezca más a PS, vaya a la pestaña Colores de las propiedades de acceso directo y establezca los valores Rojo, Verde y Azul en 1, 36 y 86 respectivamente.

captura de pantalla

usuario247702
fuente
Sencillo y funciona como un encanto. Esta respuesta merece más votos a favor.
Mark Meuer
2
Lo único que no me gusta de esto es que mantiene cargado un proceso cmd.exe redundante. Aparte de eso, es una buena solución.
orad
17

Una pregunta antigua pero que vale la pena responder a (a) proporcionar soporte a VS2013; (b) combine lo mejor de dos respuestas anteriores; y (c) proporcionar un envoltorio de función.

Esto se basa en la técnica de @ Andy (que se basa en la técnica de Allen Mack como indicó Andy (que a su vez se basa en la técnica de Robert Anderson como indicó Allen) (todas las cuales tenían un pequeño error, como lo indicó en esta página el usuario conocido solo como "yo- - ", así que también lo tomé en cuenta))).

Aquí está mi código final: tenga en cuenta el uso del cuantificador no codicioso en la expresión regular para manejar cualquier posible igual incrustado en los valores. Eso también simplifica el código: una única coincidencia en lugar de una coincidencia y luego se divide como en el ejemplo de Andy o una coincidencia y luego indexof y subcadenas como en el ejemplo de "yo -").

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
}
Michael Sorens
fuente
Para compatibilidad con PowerShell 2.0, la sección param requiere [parameter(Mandatory=$true,...
sakra
1
Agradable, pero sería mejor sin el pushd / popd. Solo use algo comocmd /c """$targetDir\vcvarsall.bat""&set"
stijn
9

Keith ya ha mencionado PowerShell Community Extensions (PSCX), con su Invoke-BatchFilecomando:

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

También noté que PSCX también tiene una Import-VisualStudioVarsfunción:

Import-VisualStudioVars -VisualStudioVersion 2013
Tahir Hassan
fuente
4
A partir de PSCX 3.2.0, este cmdlet no admite VS 2015. Abrí un problema para él.
orad
3

Felicitaciones a Andy S por su respuesta. He estado usando su solución por un tiempo, pero hoy encontré un problema. Cualquier valor que tenga un signo igual se truncará en el signo igual. Por ejemplo, tuve:

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

Pero mi sesión de PS informó:

PS C:\> $env:JAVA_TOOL_OPTIONS
-Duser.home

Arreglé esto modificando mi script de perfil a lo siguiente:

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
yo--
fuente
Hola, bonita adición. ¿Actualizarlo también con las versiones VS2015 / 17 ? Este es el primer resultado de Google, creo que su adición ayudará a la gente.
Squirrelkiller
1

Para alguien que todavía está luchando con él en 2020 y Visual Studio Code 1.41.1, un poco fuera de tema aquí.

Usando todas las diferentes partes del código de arriba e Internet, por ejemplo, de https://help.appveyor.com/discussions/questions/18777-how-to-use-vcvars64bat-from-powershell y con un enfoque paso a paso, logré tener el siguiente script funcionando.

Guardado en VSCode "settings.json" y con la extensión Code Runner instalada.

Con Microsoft (R) C / C ++ Optimizing Compiler Version "cl.exe" de 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\""}

Con Microsoft (R) C / C ++ Optimizing Compiler Version "cl.exe" de 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\""}

HTH

olin000
fuente
0

Me gusta pasar los comandos a un shell secundario así:

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

O alternativamente

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