Jak mogę używać programu PowerShell z wierszem polecenia programu Visual Studio?

119

Używam Beta 2 od jakiegoś czasu i doprowadza mnie do szału, że muszę przejść do cmd.exe podczas uruchamiania wiersza polecenia VS2010. Kiedyś miałem ładny skrypt vsvars2008.ps1 dla Visual Studio 2008. Czy ktoś ma vsvars2010.ps1 lub coś podobnego?

Andy S.
źródło

Odpowiedzi:

223

Okradając hojnie stąd: http://allen-mack.blogspot.com/2008/03/replace-visual-studio-command-prompt.html , udało mi się to uruchomić. Dodałem do mojego profile.ps1 i ze światem wszystko jest w porządku.

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

To działało dobrze przez lata - aż do Visual Studio 2015. vcvarsall.bat już nie istnieje. Zamiast tego można użyć pliku vsvars32.bat, który znajduje się w folderze 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

W programie Visual Studio 2017 sytuacja uległa zmianie po raz kolejny. vsvars32.batWydaje się, że porzucono go na korzyść VsDevCmd.bat. Dokładna ścieżka może się różnić w zależności od używanej wersji programu 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
Andy S.
źródło
6
Krótka informacja, że ​​ta sama technika działa w programie Visual Studio 2012. Po prostu zmień „Microsoft Visual Studio 10.0” na „Microsoft Visual Studio 11.0”
Andy S,
9
echo $Profileaby zobaczyć zamierzoną ścieżkę dla swojego profile.ps1, jeśli nigdy jej nie tworzyłeś
Matt Stephenson
5
Sam skrypt działa cudownie. Uwaga (prawdopodobnie): ponieważ konsola Menedżera pakietów w programie Visual Studio sama jest hostem PowerShell, ten skrypt również zostanie uruchomiony. Nie wydaje się to stanowić problemu, dopóki nie zauważysz, że „Uruchom bez debugowania” lub jakiekolwiek inne funkcje lub wtyczki uruchamiające standardową konsolę Windows nie będą działać po zainicjowaniu PMC. Obejrzałem ten problem, zamiast zapisywać skrypt w tej odpowiedzi w „profile.ps1”, zapisałem go w „Microsoft.PowerShell_profile.ps1”, aby był uruchamiany tylko w „prawidłowej” sesji PowerShell.
Chris Simmons,
3
Naprawdę złą praktyką jest twarde kodowanie ścieżek, gdy istnieją doskonale doskonałe zmienne środowiskowe (VS140COMNTOOLS dla VS2015) do użycia. To zadziała nawet w przypadku niestandardowych instalacji VS.
Voo
5
Doceniam chęć użycia zmiennych środowiskowych, ale te zmienne wydają się być inicjowane przez sam plik wsadowy, z którego próbujemy wyodrębnić zmienne. Byłbym szczęśliwy, widząc przeciwne dowody. Mam czystą instalację systemu Windows 10 z czystą instalacją programu Visual Studio 2017 i bez zmiennej środowiskowej VS150COMNTOOLS, dopóki nie wykonam VsDevCmd.bat.
Andy S,
26

Najprostszą opcją jest uruchomienie wiersza polecenia programu VS 2010, a następnie uruchomienie programu PowerShell.exe. Jeśli naprawdę chcesz to zrobić z „domowego” znaku zachęty PowerShell, podejście, które pokazujesz, jest najlepszym rozwiązaniem. Używam scenariusza, który Lee Holmes napisał jakiś czas temu:

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

Uwaga: ta funkcja będzie dostępna wkrótce w wersji opartej na module programu PowerShell Community Extensions 2.0.

Keith Hill
źródło
22

Znalazłem prosty sposób tutaj : zmodyfikować skrót.

Oryginalny skrót wygląda mniej więcej tak:

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

Dodaj & powershellprzed ostatnim cytatem, na przykład:

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

Jeśli chcesz, aby wyglądał bardziej jak PS, przejdź do zakładki Kolory we właściwościach skrótu i ​​ustaw wartości Czerwony, Zielony i Niebieski odpowiednio na 1, 36 i 86.

zrzut ekranu

user247702
źródło
Prosty i działa jak urok. Ta odpowiedź zasługuje na więcej głosów.
Mark Meuer
2
Jedyne, co mi się w tym nie podoba, to to, że utrzymuje załadowany nadmiarowy proces cmd.exe. Poza tym to fajne rozwiązanie.
orad
17

Stare pytanie, ale warte innej odpowiedzi, aby (a) zapewnić wsparcie VS2013; (b) połączyć najlepszą z dwóch poprzednich odpowiedzi; oraz (c) zapewnić opakowanie funkcji.

Opiera się to na technice @ Andy'ego (która opiera się na technice Allena Macka, jak wskazał Andy (która z kolei opiera się na technice Roberta Andersona, jak wskazał Allen (z których wszystkie miały niewielką usterkę, jak wskazał na tej stronie użytkownik znany tylko jako „ja- - ”, więc też to wziąłem pod uwagę))).

Oto mój ostateczny kod - zwróć uwagę na użycie niechciwego kwantyfikatora w wyrażeniu regularnym do obsługi wszelkich możliwych wbudowanych równań w wartościach. Zdarza się to również w celu uproszczenia kodu: pojedyncze dopasowanie zamiast dopasowania, a następnie podzielone, jak w przykładzie Andy'ego lub dopasowanie, a następnie indexof i podciągi, jak w przykładzie "ja -").

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
źródło
Aby zapewnić zgodność z programem PowerShell 2.0, sekcja param wymaga [parameter(Mandatory=$true,...
sakra
1
Fajnie, ale byłoby fajniej bez pushd / popd. Po prostu użyj czegoś takiego jakcmd /c """$targetDir\vcvarsall.bat""&set"
stijn
9

Keith wspomniał już o rozszerzeniach społeczności PowerShell (PSCX), Invoke-BatchFilepoleceniem:

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

Zauważyłem też, że PSCX ma też Import-VisualStudioVarsfunkcję:

Import-VisualStudioVars -VisualStudioVersion 2013
Tahir Hassan
źródło
4
Począwszy od wersji PSCX 3.2.0, VS 2015 nie jest obsługiwany w tym poleceniu cmdlet. Otworzyłem dla niego numer .
orad
3

Uznanie dla Andy'ego S. za jego odpowiedź. Używam jego rozwiązania od jakiegoś czasu, ale dzisiaj napotkałem problem. Każda wartość, która ma znak równości, jest obcinana przy znaku równości. Na przykład miałem:

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

Ale moja sesja PS zgłosiła:

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

Naprawiłem to, modyfikując mój skrypt profilu do następującego:

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
mnie--
źródło
Hej fajny dodatek. Zaktualizować go również z wersjami VS2015 / 17 ? To pierwszy wynik w Google, myślę, że Twój dodatek pomoże ludziom.
Squirrelkiller
1

Dla kogoś, kto wciąż boryka się z tym w 2020 roku i Visual Studio Code 1.41.1, więc trochę poza tematem tutaj.

Używając wszystkich różnych części kodu z góry i Internetu, np. Z https://help.appveyor.com/discussions/questions/18777-how-to-use-vcvars64bat-from-powershell i dzięki podejściu krok po kroku udało mi się czy poniższy skrypt działa.

Zapisano w VSCode „settings.json” i po zainstalowaniu rozszerzenia Code Runner.

Z optymalizującą wersją kompilatora Microsoft (R) C / C ++ „cl.exe” z programu 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\""}

Z optymalizującą wersją kompilatora Microsoft (R) C / C ++ „cl.exe” z programu 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
źródło
0

Lubię przekazywać polecenia do powłoki dziecka w następujący sposób:

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

Lub alternatywnie

cmd /c "`"${env:VS140COMNTOOLS}..\..\VC\vcvarsall.bat`" amd64 && <someCommand> && <someOtherCommand>"  
MatrixManAtYrService
źródło