Visual StudioコマンドプロンプトでPowerShellを使用するにはどうすればよいですか?


119

私はしばらくの間Beta 2を使用しており、VS2010コマンドプロンプトを実行するときにcmd.exeにパントする必要があるということを私に推し進めています。以前はVisual Studio 2008用の素晴らしいvsvars2008.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は存在しません。代わりに、Common7 \ Toolsフォルダーにあるvsvars32.batファイルを使用できます。

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
スクリプト自体は素晴らしいです。ただし、(おそらく)注意:Visual Studioのパッケージマネージャーコンソールはそれ自体がPowerShellホストであるため、このスクリプトもそこで実行されます。PMCが初期化された後、「デバッグなしで実行」または標準のWindowsコンソールを起動する他の関数またはプラグインの実行が機能しないことに気づくまで、これは問題に見えません。この問題を回避するには、この回答のスクリプトを "profile.ps1"に保存するのではなく、 "Microsoft.PowerShell_profile.ps1"に保存して、 "適切な" PowerShellセッションでのみ実行されるようにします。
Chris Simmons

3
使用する完全に細かい環境変数(VS2015の場合はVS140COMNTOOLS)がある場合にパスをハードコーディングすることは、非常に悪い習慣です。カスタムVSインストールでも機能します。
Voo 2016

5
環境変数を使用したいのですが、これらの変数は、変数を抽出しようとしているバッチファイルによって初期化されているようです。反対の証拠を見ていただければ幸いです。VsDevCmd.batを実行するまで、クリーンなWindows 10インストールとクリーンなVisual Studio 2017インストールがあり、VS150COMNTOOLS環境変数はありません。
アンディ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、2015年

2
これに関して私が気に入らない唯一のことは、冗長なcmd.exeプロセスがロードされたままになることです。それ以外は素晴らしい解決策です。
orad

17

古い質問ですが、(a)VS2013をサポートするための別の回答の価値があります。(b)以前の2つの回答のうち最良のものを組み合わせる。(c)関数ラッパーを提供します。

これは、@ Andyの手法に基づいています(これは、Andyが示したアレンマックの手法に基づいています(これは、Allenが示したロバートアンダーソンの手法に基づいています(このページでは、「me- -"、それで私はそれも考慮に入れました)))。

これが私の最終的なコードです-値に埋め込まれているすべての等しい値を処理するために、正規表現で貪欲でない量指定子を使用していることに注意してください。これは、コードを単純化するためにも起こります。一致の代わりに単一の一致があり、その後、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との互換性のために、paramセクションには[parameter(Mandatory=$true,...
sakra

1
いいですが、pushd / popdがなければimoはもっといいでしょう。次のようなものを使用してください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はサポートされません。そのために問題をオープンしました。
orad 2015

3

アンディ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バージョンでも更新しますか?これは最初のグーグル結果です、あなたの追加は人々を助けると思います。
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拡張機能がインストールされています。

Visual Studio 2015 / 14.0のMicrosoft(R)C / C ++ Optimizing Compilerバージョン "cl.exe"の場合:

"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\""}

Visual Studio 2019 / 16.4.3のMicrosoft(R)C / C ++ Optimizing Compilerバージョン "cl.exe"の場合:

"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.