Come posso utilizzare PowerShell con il prompt dei comandi di Visual Studio?


119

Uso Beta 2 da un po 'di tempo e mi sta facendo impazzire il fatto di dover puntare su cmd.exe durante l'esecuzione del prompt dei comandi VS2010. Avevo un bel script vsvars2008.ps1 per Visual Studio 2008. Qualcuno ha un vsvars2010.ps1 o qualcosa di simile?

Risposte:


223

Rubando liberamente da qui: http://allen-mack.blogspot.com/2008/03/replace-visual-studio-command-prompt.html , sono riuscito a farlo funzionare. Ho aggiunto quanto segue al mio profilo.ps1 e va tutto bene con il mondo.

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

Ha funzionato bene per anni, fino a quando Visual Studio 2015. vcvarsall.bat non esiste più. È invece possibile utilizzare il file vsvars32.bat, che si trova nella cartella 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

Le cose sono cambiate ancora una volta per Visual Studio 2017. vsvars32.batsembra essere stato abbandonato a favore di VsDevCmd.bat. Il percorso esatto può variare a seconda dell'edizione di Visual Studio 2017 in uso.

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
Solo una breve nota che questa stessa tecnica funziona per Visual Studio 2012. Cambia semplicemente "Microsoft Visual Studio 10.0" in "Microsoft Visual Studio 11.0"
Andy S

9
echo $Profileper vedere il percorso previsto per il tuo profilo.ps1, se non l'hai mai creato
Matt Stephenson

5
Lo script stesso funziona meravigliosamente. Una nota di cautela, però (forse): poiché la console di Gestione pacchetti in Visual Studio è essa stessa un host PowerShell, questo script verrà eseguito anche lì. Questo non sembra essere un problema fino a quando non si nota che "Esegui senza debug" o qualsiasi altra funzione o plug-in che avvia una console Windows standard non funzionerà dopo l'inizializzazione di PMC. Ho aggirato questo problema, invece di salvare lo script in questa risposta a "profile.ps1", l'ho salvato in "Microsoft.PowerShell_profile.ps1" in modo che venga eseguito solo in una sessione di PowerShell "corretta".
Chris Simmons

3
È davvero una cattiva pratica codificare i percorsi quando ci sono variabili di ambiente perfettamente corrette (VS140COMNTOOLS per VS2015) da utilizzare. Funzionerà anche per installazioni VS personalizzate.
Voo

5
Apprezzo il desiderio di utilizzare variabili di ambiente, ma quelle variabili sembrano essere inizializzate dallo stesso file batch da cui stiamo cercando di estrarre le variabili. Sarei felice di vedere prove del contrario. Ho un'installazione pulita di Windows 10 con un'installazione pulita di Visual Studio 2017 e nessuna variabile d'ambiente VS150COMNTOOLS fino a quando non eseguo VsDevCmd.bat.
Andy S

26

L'opzione più semplice è eseguire il prompt dei comandi di VS 2010 e quindi avviare PowerShell.exe. Se vuoi davvero farlo dal prompt di PowerShell "home", l'approccio che mostri è la strada da percorrere. Uso una sceneggiatura che Lee Holmes ha scritto qualche tempo fa:

<#
.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: questa funzione sarà disponibile a breve nella versione basata su modulo PowerShell Community Extensions 2.0.


22

Ho trovato un metodo semplice qui : modificare il collegamento.

La scorciatoia originale è qualcosa del genere:

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

Aggiungi & powershellprima dell'ultima citazione, in questo modo:

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

Se vuoi renderlo più simile a PS, vai alla scheda Colori delle proprietà della scorciatoia e imposta i valori Rosso, Verde e Blu rispettivamente su 1, 36 e 86.

immagine dello schermo


Semplice e funziona come un fascino. Questa risposta merita più voti positivi.
Mark Meuer

2
L'unica cosa che non mi piace di questo, è che mantiene caricato un processo cmd.exe ridondante. A parte questo è una bella soluzione.
orad

17

Una vecchia domanda ma che merita un'altra risposta a (a) fornire supporto a VS2013; (b) combinare la migliore delle due risposte precedenti; e (c) fornire un wrapper di funzione.

Questo si basa sulla tecnica di @ Andy (che si basa sulla tecnica di Allen Mack come indicato da Andy (che a sua volta si basa sulla tecnica di Robert Anderson come indicato da Allen (tutte avevano un leggero glitch come indicato in questa pagina dall'utente noto solo come "me- - ", quindi ho tenuto conto anche di questo))).

Ecco il mio codice finale: nota l'uso del quantificatore non avido nella regex per gestire qualsiasi possibile uguale incorporato nei valori. Ciò accade anche per semplificare il codice: una singola corrispondenza invece di una corrispondenza quindi divisa come nell'esempio di Andy o una corrispondenza quindi indexof e sottostringhe come nell'esempio di "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
}

Per la compatibilità con PowerShell 2.0 la sezione param richiede [parameter(Mandatory=$true,...
sakra

1
Bello, ma sarei più carino senza pushd / popd. Basta usare qualcosa comecmd /c """$targetDir\vcvarsall.bat""&set"
stijn

9

Keith ha già menzionato PowerShell Community Extensions (PSCX), con il suo Invoke-BatchFilecomando:

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

Ho anche notato che PSCX ha anche una Import-VisualStudioVarsfunzione:

Import-VisualStudioVars -VisualStudioVersion 2013

4
A partire da PSCX 3.2.0, VS 2015 non è supportato in questo cmdlet. Ho aperto un problema per questo.
orad

3

Complimenti ad Andy S per la sua risposta. Uso la sua soluzione da un po 'di tempo, ma oggi ho riscontrato un problema. Qualsiasi valore che ha un segno di uguale viene troncato in corrispondenza del segno di uguale. Ad esempio, ho avuto:

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

Ma la mia sessione PS ha riportato:

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

Ho risolto questo problema modificando lo script del mio profilo come segue:

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

Ehi bella aggiunta. Aggiornalo con le versioni VS2015 / 17 ? Questo è il primo risultato di Google, penso che la tua aggiunta aiuterà le persone.
Squirrelkiller

1

Per qualcuno che sta ancora lottando con esso nel 2020 e Visual Studio Code 1.41.1, quindi un po 'fuori tema qui.

Utilizzando tutte le diverse parti di codice dall'alto e da Internet, ad esempio da https://help.appveyor.com/discussions/questions/18777-how-to-use-vcvars64bat-from-powershell e con un approccio graduale sono riuscito a avere lo script seguente funzionante.

Salvato in VSCode "settings.json" e con l'estensione Code Runner installata.

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


0

Mi piace passare i comandi in una shell figlio in questo modo:

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

O in alternativa

cmd /c "`"${env:VS140COMNTOOLS}..\..\VC\vcvarsall.bat`" amd64 && <someCommand> && <someOtherCommand>"  
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.