How can I use PowerShell with the Visual Studio Co

2019-01-09 23:20发布

问题:

I've been using Beta 2 for a while now and it's been driving me nuts that I have to punt to cmd.exe when running the VS2010 Command Prompt. I used to have a nice vsvars2008.ps1 script for Visual Studio 2008. Anyone have a vsvars2010.ps1 or something similar?

回答1:

Stealing liberally from here: http://allen-mack.blogspot.com/2008/03/replace-visual-studio-command-prompt.html, I was able to get this to work. I added the following to my profile.ps1 and all is well with the world.

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

This has worked well for years - until Visual Studio 2015. vcvarsall.bat no longer exists. Instead, you can use the vsvars32.bat file, which is located in the Common7\Tools folder.

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

Things have changed yet again for Visual Studio 2017. vsvars32.bat appears to have been dropped in favor of VsDevCmd.bat. The exact path may vary depending on which edition of Visual Studio 2017 you're using.

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


回答2:

The simplest option is to run the VS 2010 command prompt and then start PowerShell.exe. If you really want to do this from your "home" PowerShell prompt, the approach you show is the way to go. I use a script that Lee Holmes wrote a while back:

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

Note: this function will be available in the PowerShell Community Extensions 2.0 module-based release coming soon.



回答3:

An old question but worth another answer to (a) provide VS2013 suppport; (b) combine the best of two previous answers; and (c) provide a function wrapper.

This builds on @Andy's technique (which builds on Allen Mack's technique as Andy indicated (which in turn builds on Robert Anderson's technique as Allen indicated (all of which had a slight glitch as indicated on this page by the user known only as "me--", so I took that into account as well))).

Here is my final code--note the use of the non-greedy quantifier in the regex to handle any possible embedded equals in the values. That also happens to simplify the code: a single match instead of a match then split as in Andy's example or a match then indexof and substrings as in "me--"'s example).

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
}


回答4:

I found a simple method here: modify the shortcut.

The original shortcut is something like this:

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

Add & powershell before the last quote, like this:

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

If you want to make it look more like PS, go to the Colors tab of the shortcut properties and set the Red, Green and Blue values to 1, 36 and 86 respectively.



回答5:

Keith has already mentioned PowerShell Community Extensions (PSCX), with its Invoke-BatchFile command:

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

I also noticed that PSCX also has an Import-VisualStudioVars function:

Import-VisualStudioVars -VisualStudioVersion 2013


回答6:

Kudos to Andy S for his answer. I've been using his solution for a while, but ran into a problem today. Any value that has an equals sign in it is truncated at the equals sign. For example, I had:

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

But my PS session reported:

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

I fixed this by modifying my profile script to the following:

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


回答7:

I like to pass the commands into a child shell like so:

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

Or alternatively

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