Wie kann ich PowerShell mit der Visual Studio-Eingabeaufforderung verwenden?

119

Ich benutze Beta 2 jetzt schon eine Weile und es hat mich verrückt gemacht, dass ich auf cmd.exe punt muss, wenn ich die VS2010-Eingabeaufforderung ausführe. Ich hatte früher ein schönes vsvars2008.ps1-Skript für Visual Studio 2008. Hat jemand ein vsvars2010.ps1 oder ähnliches?

Andy S.
quelle

Antworten:

223

Von hier aus großzügig zu stehlen: http://allen-mack.blogspot.com/2008/03/replace-visual-studio-command-prompt.html , konnte ich dies zum Laufen bringen. Ich habe folgendes zu meinem profile.ps1 hinzugefügt und alles ist gut mit der Welt.

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

Dies hat jahrelang gut funktioniert - bis Visual Studio 2015. vcvarsall.bat existiert nicht mehr. Stattdessen können Sie die Datei vsvars32.bat verwenden, die sich im Ordner Common7 \ Tools befindet.

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

Für Visual Studio 2017 vsvars32.bathaben sich die Dinge erneut geändert VsDevCmd.bat. Der genaue Pfad kann je nach verwendeter Edition von Visual Studio 2017 variieren.

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.
quelle
6
Nur eine kurze Anmerkung, dass dieselbe Technik für Visual Studio 2012 funktioniert. Ändern Sie einfach "Microsoft Visual Studio 10.0" in "Microsoft Visual Studio 11.0"
Andy S
9
echo $Profileum den beabsichtigten Pfad für Ihr profile.ps1 zu sehen, falls Sie ihn noch nie erstellt haben
Matt Stephenson
5
Das Skript selbst funktioniert wunderbar. Ein Hinweis zur Vorsicht (möglicherweise): Da die Package Manager-Konsole in Visual Studio selbst ein PowerShell-Host ist, wird dieses Skript auch dort ausgeführt. Dies scheint kein Problem zu sein, bis Sie feststellen, dass "Ohne Debugging ausführen" oder andere Funktionen oder Plugins, die eine Standard-Windows-Konsole starten, nach der Initialisierung des PMC nicht funktionieren. Ich habe dies umgangen, indem ich das Skript in dieser Antwort in "profile.ps1" nicht in "Microsoft.PowerShell_profile.ps1" gespeichert habe, sodass es nur in einer "richtigen" PowerShell-Sitzung ausgeführt wird.
Chris Simmons
3
Es ist wirklich eine schlechte Praxis, die Pfade fest zu codieren, wenn vollkommen feine Umgebungsvariablen (VS140COMNTOOLS für VS2015) verwendet werden können. Dies funktioniert sogar bei benutzerdefinierten VS-Installationen.
Voo
5
Ich schätze den Wunsch, Umgebungsvariablen zu verwenden, aber diese Variablen scheinen durch die Batch-Datei initialisiert zu werden, aus der wir Variablen extrahieren möchten. Ich würde mich über gegenteilige Beweise freuen. Ich habe eine saubere Windows 10-Installation mit einer sauberen Visual Studio 2017-Installation und keiner VS150COMNTOOLS-Umgebungsvariablen, bis ich VsDevCmd.bat ausführe.
Andy S
26

Am einfachsten ist es, die VS 2010-Eingabeaufforderung auszuführen und anschließend PowerShell.exe zu starten. Wenn Sie dies wirklich über Ihre PowerShell-Eingabeaufforderung "zu Hause" tun möchten, ist der von Ihnen gezeigte Ansatz der richtige Weg. Ich benutze ein Skript, das Lee Holmes vor einiger Zeit geschrieben hat:

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

Hinweis: Diese Funktion wird in Kürze in der modulbasierten Version von PowerShell Community Extensions 2.0 verfügbar sein .

Keith Hill
quelle
22

Ich habe hier eine einfache Methode gefunden : Ändern Sie die Verknüpfung.

Die ursprüngliche Verknüpfung sieht ungefähr so ​​aus:

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

Fügen Sie & powershellvor dem letzten Zitat Folgendes hinzu:

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

Wenn Sie möchten, dass es eher wie PS aussieht, wechseln Sie zur Registerkarte Farben der Verknüpfungseigenschaften und setzen Sie die Werte für Rot, Grün und Blau auf 1, 36 bzw. 86.

Bildschirmfoto

user247702
quelle
Einfach und wirkt wie ein Zauber. Diese Antwort verdient mehr positive Stimmen.
Mark Meuer
2
Das einzige, was mir daran nicht gefällt, ist, dass ein redundanter cmd.exe-Prozess geladen bleibt. Davon abgesehen ist das eine schöne Lösung.
Orad
17

Eine alte Frage, die aber eine andere Antwort wert ist, um (a) VS2013-Unterstützung bereitzustellen; (b) das Beste aus zwei vorherigen Antworten kombinieren; und (c) einen Funktionswickler bereitstellen.

Dies baut auf @ Andys Technik auf (die auf Allen Macks Technik aufbaut, wie Andy angegeben hat (die wiederum auf Robert Andersons Technik aufbaut, wie Allen angegeben hat) (alle hatten einen leichten Fehler, wie auf dieser Seite vom Benutzer angegeben, der nur als "me-" bekannt ist. - ", also habe ich das auch berücksichtigt))).

Hier ist mein endgültiger Code - beachten Sie die Verwendung des nicht gierigen Quantifizierers in der Regex, um mögliche eingebettete Gleichheiten in den Werten zu behandeln. Dies vereinfacht auch den Code: eine einzelne Übereinstimmung anstelle einer Übereinstimmung, die dann wie in Andys Beispiel aufgeteilt wird, oder eine Übereinstimmung, dann indexof und Teilzeichenfolgen wie in "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
}
Michael Sorens
quelle
Für die PowerShell 2.0-Kompatibilität benötigt der Parameterabschnitt [parameter(Mandatory=$true,...
Sakra
1
Schön, aber ohne Pushd / Popd wäre ich imo schöner. Verwenden Sie einfach so etwas wiecmd /c """$targetDir\vcvarsall.bat""&set"
stijn
9

Keith hat PowerShell Community Extensions (PSCX) bereits mit folgendem Invoke-BatchFileBefehl erwähnt:

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

Mir ist auch aufgefallen, dass PSCX auch eine Import-VisualStudioVarsFunktion hat:

Import-VisualStudioVars -VisualStudioVersion 2013
Tahir Hassan
quelle
4
Ab PSCX 3.2.0 wird VS 2015 in diesem Cmdlet nicht unterstützt. Ich habe eine Ausgabe dafür eröffnet .
Orad
3

Ein großes Lob an Andy S für seine Antwort. Ich benutze seine Lösung schon eine Weile, bin aber heute auf ein Problem gestoßen. Jeder Wert mit einem Gleichheitszeichen wird am Gleichheitszeichen abgeschnitten. Zum Beispiel hatte ich:

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

Aber meine PS-Sitzung berichtete:

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

Ich habe dies behoben, indem ich mein Profilskript wie folgt geändert habe:

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
mich--
quelle
Hey nette Ergänzung. Aktualisieren Sie es auch mit den VS2015 / 17-Versionen ? Dies ist das erste Google-Ergebnis. Ich denke, Ihr Zusatz wird den Menschen helfen.
Eichhörnchenkiller
1

Für jemanden, der im Jahr 2020 und Visual Studio Code 1.41.1 immer noch damit zu kämpfen hat, also ein bisschen abseits des Themas.

Ich habe alle verschiedenen Teile des Codes von oben und aus dem Internet verwendet, z. B. von https://help.appveyor.com/discussions/questions/18777-how-to-use-vcvars64bat-from-powershell, und mit einem schrittweisen Ansatz, den ich geschafft habe Lassen Sie das folgende Skript funktionieren.

In VSCode "settings.json" gespeichert und mit der Code Runner-Erweiterung installiert.

Mit Microsoft (R) C / C ++ - Optimierung der Compilerversion "cl.exe" aus 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\""}

Mit Microsoft (R) C / C ++ - Optimierung der Compilerversion "cl.exe" aus 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
quelle
0

Ich möchte die Befehle wie folgt an eine untergeordnete Shell übergeben:

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

Oder alternativ

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