ฉันจะใช้ PowerShell กับ Visual Studio Command Prompt ได้อย่างไร


119

ฉันใช้เบต้า 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"
Andy S

9
echo $Profileเพื่อดูเส้นทางที่ต้องการสำหรับ profile.ps1 ของคุณหากคุณไม่เคยสร้างมัน
Matt Stephenson

5
ตัวบททำงานได้อย่างยอดเยี่ยม ข้อควรระวัง (อาจเป็นไปได้): เนื่องจาก Package Manager Console ใน Visual Studio เป็นโฮสต์ของ PowerShell สคริปต์นี้จะทำงานที่นั่นด้วย ดูเหมือนว่าจะไม่มีปัญหาจนกว่าคุณจะสังเกตเห็นว่า "Run without debugging" หรือฟังก์ชั่นหรือปลั๊กอินอื่น ๆ ที่เรียกใช้คอนโซล Windows มาตรฐานจะไม่ทำงานหลังจากที่ PMC เริ่มต้นแล้ว ฉันแก้ไขโดยแทนที่จะบันทึกสคริปต์ในคำตอบนี้เป็น "profile.ps1" ฉันบันทึกลงใน "Microsoft.PowerShell_profile.ps1" เพื่อให้ทำงานในเซสชัน PowerShell "ที่เหมาะสม" เท่านั้น
Chris Simmons

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 ตามลำดับ

ภาพหน้าจอ


ตรงไปตรงมาและใช้งานได้เหมือนมีเสน่ห์ คำตอบนี้สมควรได้รับการโหวตมากขึ้น
Mark Meuer

2
สิ่งเดียวที่ฉันไม่ชอบเกี่ยวกับเรื่องนี้คือมันทำให้กระบวนการ cmd.exe ที่ซ้ำซ้อนโหลดอยู่ นอกเหนือจากนั้นเป็นทางออกที่ดี
orad

17

คำถามเก่า แต่คุ้มค่ากับคำตอบอื่นสำหรับ (a) ให้ VS2013 suppport; (b) รวมคำตอบที่ดีที่สุดของสองคำตอบก่อนหน้านี้ และ (c) ระบุฟังก์ชัน wrapper

สิ่งนี้สร้างขึ้นจากเทคนิคของ @ Andy (ซึ่งสร้างจากเทคนิคของ Allen Mack ตามที่ Andy ระบุไว้ (ซึ่งจะสร้างขึ้นจากเทคนิคของ Robert Anderson ตามที่ Allen ระบุไว้ (ซึ่งทั้งหมดนี้มีข้อผิดพลาดเล็กน้อยตามที่ระบุไว้ในหน้านี้โดยผู้ใช้ที่รู้จักกันในชื่อ "me- - "ดังนั้นฉันจึงคำนึงถึงสิ่งนั้นด้วย)))

นี่คือรหัสสุดท้ายของฉัน - สังเกตการใช้ตัวระบุปริมาณที่ไม่โลภใน regex เพื่อจัดการกับค่าที่เป็นไปได้ที่ฝังไว้ นอกจากนี้ยังเกิดขึ้นเพื่อลดความซับซ้อนของรหัส: การจับคู่ครั้งเดียวแทนที่จะเป็นการจับคู่จากนั้นแยกตามตัวอย่างของ Andy หรือการจับคู่ตามด้วยดัชนีของและสตริงย่อยดังในตัวอย่าง "ฉัน -")

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
ดี แต่ imo จะดีกว่าถ้าไม่มี pushd / popd เพียงใช้บางอย่างเช่นcmd /c """$targetDir\vcvarsall.bat""&set"
stijn

9

Keith ได้กล่าวถึง PowerShell Community Extensions (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 ไม่ได้รับการสนับสนุนใน cmdlet นี้ ฉันเปิดประเด็นให้มัน
orad

3

ขอชื่นชม Andy S สำหรับคำตอบของเขา ฉันใช้วิธีแก้ปัญหาของเขามาระยะหนึ่งแล้ว แต่วันนี้พบปัญหา ค่าใด ๆ ที่มีเครื่องหมายเท่ากับจะถูกตัดทอนที่เครื่องหมายเท่ากับ ตัวอย่างเช่นฉันมี:

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ด้วยหรือเปล่า? นี่เป็นผลการค้นหาแรกของ Google ฉันคิดว่าการเพิ่มของคุณจะช่วยผู้คนได้
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 ++ Optimizing Compiler Version "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 ++ Optimizing Compiler Version "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\""}

HTH


0

ฉันชอบที่จะส่งคำสั่งไปยังเชลล์ลูกดังนี้:

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

หรืออีกทางหนึ่ง

cmd /c "`"${env:VS140COMNTOOLS}..\..\VC\vcvarsall.bat`" amd64 && <someCommand> && <someOtherCommand>"  
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.