如何以编程方式从正在运行.exe的机器获取到MSBuild的路径?
我可以从环境中获得。net版本,但是是否有一种方法可以获得。net版本的正确文件夹?
如何以编程方式从正在运行.exe的机器获取到MSBuild的路径?
我可以从环境中获得。net版本,但是是否有一种方法可以获得。net版本的正确文件夹?
当前回答
您可能认为这里没有太多需要添加的内容,但也许现在是时候在所有版本中使用统一的方式来执行此操作了。我将注册表查询方法(VS2015及以下)与vwhere (VS2017及以上)的使用结合起来,得出了这样的结果:
function Find-MsBuild {
Write-Host "Using VSWhere to find msbuild..."
$path = & $vswhere -latest -requires Microsoft.Component.MSBuild -find MSBuild\**\Bin\MSBuild.exe | select-object -first 1
if (!$path) {
Write-Host "No results from VSWhere, using registry key query to find msbuild (note this will find pre-VS2017 versions)..."
$path = Resolve-Path HKLM:\SOFTWARE\Microsoft\MSBuild\ToolsVersions\* |
Get-ItemProperty -Name MSBuildToolsPath |
sort -Property @{ Expression={ [double]::Parse($_.PSChildName) }; Descending=$true } |
select -exp MSBuildToolsPath -First 1 |
Join-Path -ChildPath "msbuild.exe"
}
if (!$path) {
throw "Unable to find path to msbuild.exe"
}
if (!(Test-Path $path)) {
throw "Found path to msbuild as $path, but file does not exist there"
}
Write-Host "Using MSBuild at $path..."
return $path
}
其他回答
对于Windows 7中的cmd shell脚本,我在批处理文件中使用以下片段来查找. net Framework版本4中的MSBuild.exe。我假设版本4存在,但不假设是子版本。这不是完全通用的,但对于快速脚本来说可能是有帮助的:
set msbuild.exe=
for /D %%D in (%SYSTEMROOT%\Microsoft.NET\Framework\v4*) do set msbuild.exe=%%D\MSBuild.exe
对于我的使用,我退出批处理文件的错误,如果这不起作用:
if not defined msbuild.exe echo error: can't find MSBuild.exe & goto :eof
if not exist "%msbuild.exe%" echo error: %msbuild.exe%: not found & goto :eof
如果你想编译一个Delphi项目,请在使用msbuild+Delphi2009时查看“ERROR MSB4040 There is no target in the project”
正确答案是:“有一个批处理文件称为rsvars.bat(在RAD Studio文件夹中搜索它)。在调用MSBuild之前调用它,它将设置必要的环境变量。如果编译器的位置与默认位置不同,请确保rsvars.bat中的文件夹是正确的。”
这个bat不仅会将PATH环境变量更新到正确的。net文件夹,并使用正确的MSBuild.exe版本,还会注册其他必要的变量。
本处地点
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\2.0
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\3.5
给出可执行文件的位置。
但如果你需要保存任务扩展的位置,它是打开的
%ProgramFiles%\MSBuild
在没有其他工具的情况下,从注册表中批量检索msbuild 15 (Visual Studio 2017)的路径:
set regKey=HKLM\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7
set regValue=15.0
for /f "skip=2 tokens=3,*" %%A in ('reg.exe query %regKey% /v %regValue% 2^>nul') do (
set vs17path=%%A %%B
)
set msbuild15path = %vs17path%\MSBuild\15.0\Bin\MSBuild.exe
更好的可用工具:
vswhere:定位Visual Studio 2017和更新的安装,参见get msbuild15 path with batch(使用硬编码路径,如上面的代码片段)。 使用Microsoft.VisualStudio.Workload.MSBuildTools安装VisualStudio PowerShell模块
获取最新版本的MsBuild。 最好的方法,对于所有类型的msbuild安装,不同的处理器架构(Power Shell):
function Get-MsBuild-Path
{
$msbuildPathes = $null
$ptrSize = [System.IntPtr]::Size
switch ($ptrSize) {
4 {
$msbuildPathes =
@(Resolve-Path "${Env:ProgramFiles(x86)}\Microsoft Visual Studio\*\*\MSBuild\*\Bin\msbuild.exe" -ErrorAction SilentlyContinue) +
@(Resolve-Path "${Env:ProgramFiles(x86)}\MSBuild\*\Bin\MSBuild.exe" -ErrorAction SilentlyContinue) +
@(Resolve-Path "${Env:windir}\Microsoft.NET\Framework\*\MSBuild.exe" -ErrorAction SilentlyContinue)
}
8 {
$msbuildPathes =
@(Resolve-Path "${Env:ProgramFiles(x86)}\Microsoft Visual Studio\*\*\MSBuild\*\Bin\amd64\msbuild.exe" -ErrorAction SilentlyContinue) +
@(Resolve-Path "${Env:ProgramFiles(x86)}\MSBuild\*\Bin\amd64\MSBuild.exe" -ErrorAction SilentlyContinue) +
@(Resolve-Path "${Env:windir}\Microsoft.NET\Framework64\*\MSBuild.exe" -ErrorAction SilentlyContinue)
}
default {
throw ($msgs.error_unknown_pointersize -f $ptrSize)
}
}
$latestMSBuildPath = $null
$latestVersion = $null
foreach ($msbuildFile in $msbuildPathes)
{
$msbuildPath = $msbuildFile.Path
$versionOutput = & $msbuildPath -version
$fileVersion = (New-Object System.Version($versionOutput[$versionOutput.Length - 1]))
if (!$latestVersion -or $latestVersion -lt $fileVersion)
{
$latestVersion = $fileVersion
$latestMSBuildPath = $msbuildPath
}
}
Write-Host "MSBuild version detected: $latestVersion" -Foreground Yellow
Write-Host "MSBuild path: $latestMSBuildPath" -Foreground Yellow
return $latestMSBuildPath;
}